Skip to content

docs: the tasks manual points task.parallel at Tasks, not Spending (#1454) - #1886

Open
7vignesh wants to merge 3191 commits into
Agent-Field:devfrom
7vignesh:fix/1454-tasks-at-once-manual-category
Open

7vignesh wants to merge 3191 commits into
Agent-Field:devfrom
7vignesh:fix/1454-tasks-at-once-manual-category

Conversation

@7vignesh

@7vignesh 7vignesh commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What changed

The tasks manual located task.parallel in category "spending", but /settings shows it under Tasks as tasks at once (settings.go has Category: CategoryTasks, Label: "tasks at once"). Someone following the page searched the wrong section (#1454).

  • internal/manual/chat/tasks.md: the setting now reads "under Tasks as tasks at once", naming the section and the row exactly as drawn.
  • internal/manual/chat_test.go: two probes ("where is the tasks at once setting", "what section is task.parallel under") assert the question reaches the tasks page.

How it was checked

internal/manual does not fail on my Windows checkout only because of CRLF working-tree line endings (three unrelated character-count/blank-line tests), which the committed files (LF, confirmed via git ls-files --eol) and CI never see. So I verified on a clean LF checkout in a golang:1.26 Linux container:

  • The whole internal/manual suite passes with this change applied (git reset --hard + git apply the patch, then go test ./internal/manual/).
  • The three character-count tests that fail on my CRLF working tree pass on the LF checkout, confirming they are not related to this change.
  • TestTheChatManualAnswersTheQuestionsPeopleAsk (which runs the probe table) passes, so both new probes reach the tasks page.

Checklist

  • A change entry - docs/changes/unreleased/1886-tasks-at-once-manual-category.md.
  • The manual knows about it - this IS the manual fix; no slash command, key, tool, default, limit or refusal moved.
  • No new line in .github/known-red.txt.
  • Only my own paths are staged.

Closes #1454.

santoshkumarradha and others added 30 commits September 11, 2026 23:10
… (review needed) (Agent-Field#966)

* engine: an idle conversation on an older build is named on the way in

A host one build behind holding only an IDLE conversation — the turn
finished, the person stepped away — was asked to go, went, and the window
opened on the fresh build without a word. The busy-host notice from Agent-Field#691
covered work in flight, but a conversation merely kept warm read as not
busy, so the person was never told the engine answering them had been a
build behind. They debugged a fix that had simply not reached the
conversation yet.

The notice is now owed whenever the older same-wire build is the one
answering, and it names what was held: still holding work, or only holding
the conversation. A host that went quietly says it was an older build and
that it is current now.

* changes: entry for Agent-Field#966

* engine: the headless --once road carries the stale-host notice on stderr

The notice is joined into the surface's entry notice, but --once opens no
surface, so a scripted caller against an idle stale host heard nothing —
the same silence the interactive road just fixed. It goes to stderr, the
channel a scripted caller reads, leaving stdout to the answer alone.
…reach their page first (Agent-Field#978)

* manual: two cold questions reach their page first instead of fourth, so the floor has margin

MEASURED FIRST, on dev c495991 with the gate green: 8 of the 22 held-out
questions reach their page first, 9 reach it only within the top four, 5 miss,
and the floor is 17 = 8 + 9 exactly. So the floor did not have one thin probe —
it had NINE simultaneously load-bearing ones, and any of the nine slipping out
of fourth place reddens every open pull request. That is what cost four lanes an
evening: Agent-Field#933 lost one question by a hair to a section about a tick's cell, and
the gate reported an aggregate with no per-question ownership, so it took a
bisect to find out which.

Two of the three fourth-place probes are now first:

  how do I send it a photo                    4th -> 1st   attaching-files
  how do I tell it which project to work on   4th -> 1st   choosing-a-folder

  held out   first 10/22 -> 12/22   ·   within top 4  18/22 -> 18/22
  the hundred-probe plain table    unchanged, nothing lost a place

EACH WAS MEASURED AND ONLY THE FORM THAT MOVED WAS KEPT. attaching-files took
the asker's words into its EXISTING heading and went first. choosing-a-folder
did NOT move that way — the same edit to its heading left it fourth — because
its `/folder` section is four thousand characters and loses on length
normalisation however many of the asker's words the heading carries. A short
section of its own took it first. That is the form Agent-Field#973 proved works, and the
correction it forced on the folklore this repository was passing around: a new
`## ` heading is a HAZARD to be measured, not a prohibition to be obeyed. What
is forbidden is adding one and trusting it.

AND THE NEW SECTION SAYS WHAT THE PAGE SAYS. The first draft claimed the chosen
folder's name is on the status line, which contradicts this page's own law five
hundred lines down — what choosing a folder does is make the conversation ABOUT
it, while where aforge is standing does not move. Corrected before it shipped,
and it points at the section that owns the distinction rather than restating it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(changes): number the entry with the pull request it belongs to

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(changes): the length cap and the retrieval floor are one law, not two

Lane P's reframing of this change's own finding, and it is better than the
finding was. I had written "a long section resists its heading". What is
actually true is that CLAUDE.md's "keep each section under ~2000 characters and
self-contained" IS the retrieval rule: BM25 normalises by length, so a section
past the cap is already hard to reach whatever its heading says. Measured on
this page — the `/folder` section is 3825 characters and would not move to first
place however many of the asker's words its heading carried, while a
600-character section on the same page took the same question to first.
choosing-a-folder.md has nine sections over the cap, up to 5079.

That matters because of WHEN each rule can be followed. "Measure both forms"
only helps somebody who already has a retrieval failure to diagnose. "Keep the
section under two thousand characters" is a rule they can follow while writing,
before anything is red — and it now has a measured reason rather than reading as
a preference about how much prose a person wants at once.

It also gives the choice between the two forms a cheap test instead of
judgement: `wc -c` the section. Under the cap, put the asker's words in the
heading. Over it, split the section — which fixes both laws at once — or write a
short one beside it. Splitting is the better instrument where there is room,
because an over-cap section is a defect on its own terms and not only when a
probe finds it. Not done here: nine sections is its own piece of work.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(changes): name the section this change checked its claim against

Lane P's proposed shape for the one failure the manual gates cannot catch, tried
here on the change that found the need for it rather than argued about.

CLAUDE.md is explicit that the gates check a name is MENTIONED and never that the
claim around it is true — a tool named in a "what aforge cannot do" section
satisfies them perfectly while lying. It also already obliges a lane landing a
capability to grep the corpus for the old denial. So the honest statement is not
that there is no mechanism; it is that there is a stated obligation with nothing
behind it.

This entry now names the section it checked against. It is not a gate and could
not be made into one cheaply. It is a prompt to do the read, written where a
reviewer can see whether it was done — and the read is what caught this change's
own false sentence, which no test in this repository would have.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…-Field#917)

* task: c code recommendation

Co-Authored-By: aforge <agentfield-bot@users.noreply.github.com>

* Drop the since-you-left heading gloss as redundant with the heading itself

* Remove the needs-you heading gloss — its group line already explains the panel

---------

Co-authored-by: aforge <aforge@localhost>
Co-authored-by: aforge <agentfield-bot@users.noreply.github.com>
)

* A split drawing reaches the boundary its own cut opened

A mark's drawing rides beside the next step and its one power over the
work is the interruption: cut the request in flight so the boundary where
the drawing can be SPENT arrives at once. Two orderings took that promise
away, and both ended the same way — the turn paid for a whole extra step,
and where that step was its last the drawing was written down as a
carry-on and nothing was handed anywhere (Agent-Field#956).

The reading published its answer only once `act` had RETURNED, so the
boundary the cut bought read the reading as still in flight and let it
pass; `take` is non-blocking by construction and cannot wait for it. The
answer is published first now, and one claim (`sidecar.spent`) orders the
interruption against the taker: whichever arrives first is the one that
happens, so a reading whose answer has already reached a boundary raises
no interruption into whatever the turn does next.

And a cut that arrived between one step ending and the next beginning
found nothing to cut and was dropped. Which cuts may be dropped is a
property of the reading behind them and is declared by the cause
(`boundaryCut`): a recall's block is in the transcript before its cut is
raised, so the request being assembled carries it either way, while a
drawing rides no transcript at all. So a boundary cut is OWED rather than
spent on nothing, and `beginGeneration` — already the one place that
decides whether there is anything to cut — spends it the instant there
is. It belongs to the turn that asked for it, by number, so a cut one
turn never spent cannot reach the next person's message.

And on the one road where a drawing genuinely lands too late — a turn
that answered in words has no boundary after it — the row says what the
reading said rather than the opposite of it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSshDkszBQ9RpR4dPsC5fQ

* docs: the change entry for the split drawing

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSshDkszBQ9RpR4dPsC5fQ

* The claim gates the interruption, and a cut nobody needs is withdrawn

Review of Agent-Field#962 found three things, and the first is a path this change made
worse than it found it.

sidecar.spent narrows the window where an interruption is delivered for an
answer a boundary has already taken; it does not close it. Between the settle
closing and the claim being made, the interruption can still win while a taker
at that same boundary takes anyway. Nothing is lost — the drawing is in hand —
but at a boundary there is no live generation, so the cut is now OWED rather
than dropped, and on the arms where the turn takes the drawing and carries on
(`handOverRunningTurn(...).moved == false`, `checkpointSettle`'s `ctx.Err()`)
it stops the next step for a reading that has already been read. Before this
PR the same race was a harmless drop.

So the boundary that takes the drawing withdraws the cut it no longer needs
(`Agent.dropOwedCut`), which is exact rather than racy: the take and the spend
are both on the turn's own goroutine. And `spent`'s doc says what it does — it
gates the interruption, it does not order the take.

The structural law was satisfied by a rename: it matched the identifiers
`close` and `act`, went green when no call named `act` was found, and accepted
any channel close. It now finds the reading and the interruption by their
SHAPE — the reading answers, the interruption does not — requires the settle to
be the channel closed, and fails closed when the door never delivers its
interruption at all.

And the claim now has a test in the direction it exists for: a taker that has
claimed an answer raises no interruption, plus the withdrawal and the fact that
one reading never withdraws another's cut.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: the change entry names the claim's shape and Agent-Field#984

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* lane: a running stream teaches the ledger mid-stream, in non-overlapping windows

Every lane.Sighting was built at settlement, so a stream producing tokens
for minutes taught the belief the chooser ranks on nothing until it closed.
The 14:32 retry of 2026-09-11 picked the same collapsed Morph endpoint the
14:29 call was still being throttled by, because the belief still described
that machine's morning.

The read loop already holds the live figures; it now folds a partial
sighting in at most once a minute, each window covering only the span since
the one before it, and the settlement sighting is rebased to cover only the
tail no partial claimed. One stream is one measurement, told in chapters,
never the same span twice.

Issue Agent-Field#891 §1. PR Agent-Field#924 took the live-wire rescue; this is the teaching seam
it deliberately did not.

* changes: entry for Agent-Field#964
…ask beside its worker arms it (Agent-Field#958) (Agent-Field#987)

* A refusal is about the parts, not the width: the judge that reads a task beside its worker arms it

A `/task` the sizing judge called wide, whose first set of parts the reviewer
then read together and refused, ran to the end of its life with no way to divide
at all — however much of the material it opened, and however plainly the parts
were there. The judge used to answer before the node was admitted, so its yes was
one of armDivision's signals and the worker was CONSTRUCTED holding divide_work;
once the judge moved beside the worker, so that nobody waits through it, that yes
arrived after the belt was built and did nothing but draw parts. A refusal is a
finding about the parts that were drawn, and it never un-judged the width.

The yes is the arming again, through one door. armDivisionBeside banks the answer
where the arming reads it and asks armDivision the question admission asks — so a
harness design, a quick task, a part of somebody else's division and work already
armed are refused by the very lines that refuse them at admission, rather than by
a second list that would drift from the first. On a yes it writes the word through
TaskNode.armAfterAdmission, the only writer of that word outside admission, then
appends divide_work to the running belt through armFamily and re-renders the
system prompt through rerenderSystemLocked: in that order, off that one write, so
the belt and the prompt cannot be built from different answers. It happens before
the parts are weighed, so every road out of the weighing — the reviewer's no, the
floor, the lanes, a yes too thin to be a division — leaves the worker able to hand
out what it finds once it has opened the material.

rerenderSystemLocked is one function now for the three ways a running agent's
config moves: the clock going stale, a conversation anchoring to a project, and
this.

Tests: the real /task door with a stub provider, asserting the tool names the wire
carried on the first request and the running worker's own belt and instructions
after the refusal; the control, where the judge says no and neither gains
anything; and a law that the arming word has three writers and no fourth. The
wide-task test that asserted the word stayed empty was asserting the defect, and
now reads the judge's own word.

Closes Agent-Field#958

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changes: the entry for Agent-Field#958

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…he winning arm (Agent-Field#990)

* Revert "lane: a running stream teaches the ledger mid-stream (Agent-Field#964)"

This reverts commit 75af6ee.

* docs: the change entry for the revert of Agent-Field#964

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…way net (Agent-Field#923)

* The turn decides, informed; promotion inherits; the ceiling is a runaway net

A one-line read-only design question read home-panel files for ten rounds in
48 seconds and was taken away from the conversation that was answering it. The
round-10 ceiling fired, a summary reader said `split`, and a cold worker opened
on a brief plus stub pointers: its first six calls re-read the chat's own
results, then fourteen more files, 551k input tokens at 24% cached over 393
seconds, and it never ticked an item. Three things were wrong at once. The
decision was made by the wrong party — a reader of a summary rather than the
model holding the context. It was made on the wrong signal — a count of rounds,
which measures nothing about whether the work is going anywhere. And the move
threw away everything the turn had read.

So the count no longer moves anything, and what it buys instead is a sentence.

THE TURN DECIDES, INFORMED. The rungs below the last one call nobody and move
nothing. They put one note into the running turn at its next step, through the
one ambient door a loop nudge already uses: the facts it cannot see about itself
(rounds so far, distinct files read, bytes of results held) and the three roads
on, in plain words — answer now; carry the rest on in a room with `quick_task`
and `inherit`; hand out what it has not read. The cost is stated once, where the
choice is: a worker that does not inherit opens on a brief about your work
instead of on your work, and reads it all again. No timer, no model call, no
message[0].

PROMOTION INHERITS. `quick_task` gains `inherit`: the worker is a read-only fork
of the caller's transcript, so its first request carries the caller's messages
and tool results verbatim and it reads nothing twice. It is bounded by a
property rather than a number — refused, in a result the model reads, when the
caller's context does not fit the worker model's own working room
(`compactThresholdOf`, the build's own line for how far a conversation may
grow), and the refusal names the road still open.

THE RUNAWAY NET. `readMark` survives as the last rung only, and it no longer
asks about rounds: it fires when the turn's context has passed the room it can
still work in, when the loop detector has already nudged twice, or when the wall
has run out. Each of those is a fact the build already had. A turn reading ten
files in 48 seconds reaches none of them.

AND THE CARRY-ON ROAD PROMOTES. When the net does fire, the carry-on goes
through the same admission door as the tool, with the drawn items as its
checklist and the context inherited. The brief road survives only where
inheritance cannot go — the rung that fired because the context is too big to
carry — and there the brief now carries the compiled results themselves rather
than pointers at calls the worker would have to run again.

Deleted with it: `checkpointSplitNote` and the `split` decision, the seam mark,
`quickFromDrawing`'s bare-spec path, and the stub-pointer section for an
inherited worker.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The late-drawing fixture buys its reading at the net, not at the first mark

Agent-Field#962's fixture holds a drawing past the turn's last step, and it opened that
window by crossing the FIRST mark. With the rungs below the last one buying
nothing, the first mark asks nobody, so the fixture now takes the turn to THE
RUNAWAY NET instead: every scripted round reports a fuller window
([checkpointFillAt]) until the context bound fires, and the note rungs' own
rows are dropped from what it returns, because a row that cost no call is not a
row about a drawing landing late.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* manual: the page about a brief that could not be written carries the asker's words in its heading

The probe "the run said the brief could not be written, what happened" reached
adaptive-runs in the last of four slots on dev and lost that slot once this
change's task pages said more about briefs. Retrieval is the feature, so the
heading now says it the way a person asks it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…Field#935)

* The person's word wins at the request, never at the next turn

A model a person names while work is running used to land at the next TURN.
For a conversation that is seconds; for a task step it is up to twenty
minutes. On 2026-09-11 a step sat thirteen minutes into a wait, the owner
picked another model and typed continue, the room answered `its next turn
takes it`, and the step was still talking to the model they had moved off a
minute later.

The pick now reaches the work at the next REQUEST, within lane.SpokenWithin,
through one door:

- activeGeneration carries the turn's own partial buffer, so
  `productive()` — has this request produced anything a person could use —
  is a state read of the text already on their screen rather than a second
  count of the same deltas.
- Agent.hearModelLocked is the one place a person's model reaches running
  work: it records the word for the boundary and, when the request has
  produced nothing, cuts it through cutGenerationLocked with a third cause,
  errPersonCut. It answers ModelLandsNow or ModelLandsNextRequest.
- runTurn re-reads the word at ONE site, the top of the request ladder, and
  starts the chain again from the model they named. freshModel is now the
  one place a model gets a whole budget of its own; the rescue hop calls it
  too.
- The room says which of the two happened — `switching now` or `the next
  request takes it` — and never the word "turn". RetargetTask carries the
  landing, over the wire as well.

generation_law_test.go fails the build on a second place that cancels a
generation. The manual's five claims about "the task's next turn" are
replaced by what is true, and models-and-cost.md gains the section somebody
asks for when they press a model mid-reply.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSshDkszBQ9RpR4dPsC5fQ

* docs: the change entry for Agent-Field#935

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSshDkszBQ9RpR4dPsC5fQ

* The beat law follows the door to the function it hands to

SetModel is one line now — the work and the answer to when the pick lands
live in setModel beside it — and the law that says a picked model reaches
the lane beat was reading the door's own body. It reads the road the pick
takes, and still cannot be satisfied by a door that does nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSshDkszBQ9RpR4dPsC5fQ

* The model-latch fixture pins the arm that is still true

TestSetModelAppliesFromTheNextTurn asserted the contract this change
replaces — a swap landing at the next TURN — so it was the defect written
down as a test. What is still true from that seat is the case with nothing
in flight to let go of: a word said while a tool is running is cut from
nothing and rides the very next request. personsword_test.go holds the
other two arms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSshDkszBQ9RpR4dPsC5fQ

* The person's word is the head of every chain

A failing step walked its own fallback ladder past a model the person had
just named, and a step whose completer offers no chain ended the turn on
"there is nowhere else to try" with their choice unasked.

The move takes the word where the move is really made, so the line a person
reads names the model their reply actually went to rather than a rung the
boundary was about to overrule. takeTheModel is the one place a step changes
model, and `root` — whose chain this is, a fact about the move and not about
who made it — is the only thing that differs between the two roads. The
reading of whether a step can move at all PEEKS at the word, because it runs
on every failure including the ones that ask the same model again.

Three stale comments go with it: SetReasoning claiming a level latches
"exactly as the model does" when the two rules are now deliberately
different, auxiliary.go's errand floor, and completeWithRetry's "2s, 4s, 8s,
max 3 retries" — budgets deleted before the recovery wave.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSshDkszBQ9RpR4dPsC5fQ

* Agent-Field#925's two conversation sentences are false now, so they go

The rebase carried Agent-Field#925's words onto a tree where the cut makes them
untrue. `a pick in a conversation you are sitting in front of still
lands on your next message` and `a model you pick with /model does not
redirect a rescue that is already happening` were both true on the day
they were written and neither survives the request boundary: a pick
lands on the next REQUEST, and a person's word is the head of the chain.

The room's own sentence loses its rescue clause with them. It was worth
a clause while the pick had to wait for a move somebody else made; now
the next request carries the pick whether that request is a rescue, a
retry or the step's own next step, so naming the rescue would name one
road out of three.

Agent-Field#925's `TaskNode.picked` is untouched. It owns where a node's NEXT
WORKER is built and this owns the request already out — two scopes, no
second mechanism.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* One reading of what the person has read, and one door for every word

Four things the review found, and all four are the same shape: a rule
stated in one place and answered in two.

ONE READING. `has anything reached the person` had two answers five
lines apart in the same stream observer. The recall's gate counted a
reasoning delta; the person's word did not, and said so on the page —
`thinking where nobody can read`, which the code contradicts, because
visible thinking is drawn and Agent-Field#760 made a reasoning-only turn something
somebody watches. `reachedThePerson` is the one reading now: a word of
the answer, a word of visible thinking, or a tool row formed far enough
to be spoken. `recallAside.token` is deleted and the aside reads the
turn's own. A person's word can no longer let go of a request that has
drawn anything at all, which is also what closes the withdrawal gap: the
state where a cut takes a thought off somebody's screen is unreachable
rather than handled.

ONE DOOR FOR EVERY WORD. `continue` typed into a room was enqueued and
never heard — drained when the request it interrupted ended, which on
the owner's own step was thirteen minutes later. That is the other half
of the 14:40:10 evidence and the report claimed it was already done. A
direction goes through the same hearing door the pick does. The CAUSE is
the caller's, and it is the one thing that genuinely differs: a model
changes what the next REQUEST rides, so it is answered at the request
boundary; words change what the next STEP carries, so a direction takes
the conversation's own `errSteerCut` and returns to the boundary where
queued lines are drained.

THE ROOM IS TOLD. The cut sends `EventRetrying` with `Next` naming the
model they chose — the one door that already means `this attempt is
void` — so the wait a person spoke to end stops counting. And the
waiting line no longer says `trying again` when the news is a move: the
row it is composed from says `moving to <model>`, and somebody who
picked a model should not be told their choice was a failure being
recovered from. A rescue hop's status line agrees with its own row now
for the same reason.

THE LAW FOLLOWS THE VALUE. The one-door test matched three tokens, so a
local named `generation` — which `completeWithRetryReasoning` already
binds — walked past it. It enumerates every road that hands out a
generation and flags anything reached by one, however it is named.

And the door compared a pick against the SESSION's model rather than the
one a rescued step is riding, which cost a whole cut request when
somebody picked the fallback the step was already on. `Agent.riding`
publishes what the ladder always knew.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* The person's word is not a boundary cut, and the one door holds both

Agent-Field#962 landed mid-review with `boundaryCut`: a cut whose REASON rides no
transcript is owed rather than dropped, and `beginGeneration` spends it.
The rebase composes cleanly because both changes are about the same
door — Agent-Field#962's owed-or-dropped decision lives in `cutGenerationLocked`,
which this lane had already made the single cancel site, and
`beginGeneration` spends the owed cut THROUGH that door rather than
reaching for the handle it is holding.

Neither of this lane's causes is a boundary cut, and the test Agent-Field#962
states is what says so. `errPersonCut`'s reason is written to
`Agent.spokenModel` before the cut is raised and taken from there at the
request boundary; a direction is on the worker's queue before its cut.
Both ride something the next request reads either way, exactly as a
recall's block rides the transcript — so a word arriving between two
requests needs no cut at all, and owing one would cancel a request that
was about to be right.

And this cause has a second reason of its own: an owed cut reports
itself answered, and that answer is what the room says out loud. A
person would read `switching now` over a pick that is in fact riding the
next request.

The one-door law was re-run against Agent-Field#962's new spend site and catches
the shortcut Agent-Field#962's own doc warns about: `active.cancel(owed.cause)`
inside `beginGeneration` fails it by name and line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Three from the review: the shared reading is safe, withdrawn, and on a page

(a) `recallAside.reached` replaced an atomic.Bool with a plain pointer
written by the turn's goroutine and read by the sidecar's — a race
whether or not anybody ever observed it. It is an `atomic.Pointer` now,
and a nil load is simply a reading not handed over yet, which
`reachedThePerson.did` already answers as "nothing has reached them" —
the safe answer and the one that was true at that instant. Proved under
`-race` over the recall, memory and person's-word fixtures.

(b) `StreamReplaced` reset the four buffers and not the reading. What
the dead machine drew is withdrawn on the event it sends, so the person
has none of it in front of them — and a reading left standing would tell
every door that may re-ask the request that they still do.

(c) `let go of because you chose another model` is a string a person
meets when they read a long step back, so models-and-cost.md has a
section for it beside the other log-row questions: it is not a failure,
here is why it is written down anyway, and it carries no door, so
nothing reading the log to ask "did this turn end" counts their own act.
A new heading rather than prose added to an existing one — the held-out
score goes from `first 10/22` to `first 12/22` and holds top-4 at 18.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test: a word said between two requests is not owed a cut

The next request already carries the model the person named, so cutGeneration
must answer false when nothing is running; otherwise the room says
"switching now" for a request that is not starting.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…(review needed) (Agent-Field#992)

* permissions: the frame names its way out wherever the pointer stands

Agent-Field#946's frame and Agent-Field#985's grading landed within a day of each other and
disagreed about one row. Agent-Field#946 was cut before the gate graded, so it drew
`safe answer` on `deny all` only while the pointer was ON `deny all` —
the same sentence then, because Agent-Field#933 opened every permission on the
refusal. Agent-Field#985 made an ordinary call open on `allow all`, and the mark
went missing from exactly the frames where the pointer stands on the act
and the way out most needs naming. A panel of ONE never lost it:
questionPanelOption marks any hands-only answer that loses nothing,
whatever the pointer is doing.

`deny all` is the answer that loses nothing by construction — the frame
forms only where every member has one, and the row sends each question
its own — so it now says so on every frame, which is one rule with the
panel's rather than a second one.

TestPermissionsFromOneStepAreOneFrame was the other half, and the red on
dev: it read a costly set as opening on `deny all`, which was Agent-Field#933's rule
and is no longer anyone's. It now asserts the pointer the grading puts
there and, separately, that the refusal is named though the pointer is
not on it.

The manual's grouped-frame section, the gallery caption and the e2e
needle's reason all still explained the deny-first pointer; each now says
what is true and what expired with the grading. internal/e2e's live
assertion is unchanged and was the corroboration: it waits for `safe
answer` on four ordinary reads, so it would have gone red on the next
live run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* permissions: one predicate decides the safe answer, on a panel and on a frame

From the architecture review of Agent-Field#992. The first fix marked `deny all`
unconditionally, which was a second spelling of a rule questionpanel.go
already owned — and a wrong one: a frame whose member carries its asker's
pick, or whose calls are plainly reversible, marked a row that its own
tabs leave bare, so `2 one by one` contradicted the frame it was pressed
from.

questionMarksSafe is now the one predicate, questionSetMarksSafe folds it
over a set exactly as questionGroupStart folds the pointer's rule, and
the word is read only through questionSafeAside.
TestTheSafeAnswerIsMarkedByOnePredicate fails any file that spells
questionSafeWord for itself, so a third drawing of a question cannot
invent a third rule about when a person is told where their way out is.

The frame test pinned the mark with a frame-wide substring, which passed
just as happily with the mark moved onto `allow all` — the one reading
that tells a person their keystroke loses nothing when it grants four
calls. It is a row assertion now, through questionRowSaying, and it
checks `allow all` does NOT wear it. The `wary` case asserts the opposite
of what it did, and says why.

Nothing checked a FRAME's pointer against the gate's own grade — the live
needle for that screen is the mark, which is now deliberately
pointer-independent. TestTheFrameOpensWhereTheEngineGradedTheCalls does,
with no model: the grave control is read from
internal/session/testdata/consentask-rm-rf.json and must refuse to join a
set, and the ordinary answers are session.AnswerOptions' own.

The manual said `enter` on an untouched permission denies, in two places,
which Agent-Field#953 made false. Both now split the MARK from the POINTER, and what
`safe answer` means gets its own heading in the asker's words rather than
a clause inside the grave case — it is drawn on every approval. The frame
section lost the paragraph that split its answer list and gained a
heading of its own, and the phone-width claim is scoped: under sixty
columns there is no frame and no mark at all.

The lifetime row's "THIS TEST FAILS THE DAY THE GRADING LANDS (Agent-Field#953)" is
rewritten wherever it appears: the grading landed, nothing went red, and
whether the row is owed is issue Agent-Field#995. DESIGN.md's pointer bullet carried
the pre-grading rule and now carries the stakes rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ield#1001)

The sentence told a person to run `aforge engine --stop` with no
--workspace. That flag resolves to the HOME directory, never to the
workspace being complained about, so copying the line exactly as written
from inside a checkout stopped the healthy home engine and left the
offending one running — and the line came back on the next launch,
forever.

Measured on the owner's laptop before the fix: a host on wire 14, started
2026-09-11 11:23 from a dirty build, still holding the aforge-v2 workspace
twenty-two hours and eight rebuilds later. Every launch in that checkout
read the refusal, and every remedy typed from it stopped the wrong host.
`aforge engine --stop --workspace <the checkout>` retired it at once.

The workspace comes from the host's OWN answer, remote.HostSelf.Workspace,
rather than from what this process thinks it opened: the sentence is about
the machine that will not let go, so the words a person types have to name
what IT is holding. A host too old to fill the field keeps the bare
command rather than being given an invented path.

sessionHeldElsewhereSentence in chatv3.go already spells the flag for this
exact reason, and its comment names this function as its voice. The voice
was the one place not doing it.

The version-mismatch branch is untouched. Refusing to splice a surface
onto a host whose frames it cannot read is right, and the gentler
busyEngineHostSentence road cannot honestly be offered across
incompatible wires.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…nd two orphan packages (Agent-Field#991)

* ignore macOS Finder litter

The tracked Finder metadata was accidental repository noise. Remove it and
teach the ignore file not to admit another copy.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* retire private planning dumps

Move the lasting routing and harness research into the documentation tree,
remove superseded root planning artifacts, and keep surviving references
self-contained.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* prune superseded plan documents

The deleted plans describe retired branches, surfaces, or research snapshots.
Keep their live contracts in the current architecture and design records.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* keep only summarized design evidence

Raw experiment cells and the generated home-design export duplicated retained
reports and decisions. Remove the captures while preserving their conclusions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* make retained paths portable

Machine-specific paths leaked from benchmark defaults, captured reports, and
source comments. Express the same locations through home-relative or neutral
placeholders without changing harness behavior.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Remove orphan voice and gate packages

The voice and gate packages had no importers anywhere in the tree. Remove
them, their tests, and the structural-law entries their files had occupied;
git grep proved both package import paths unused before deletion.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Remove unreachable Go functions

Remove 68 functions reported unreachable from every main and test by
deadcode -test ./..., together with the imports and private data they stranded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* the captured frames and the benchmark defaults name nobody

169 of the retained terminal captures under docs/design/polish/frames carried a
developer's home directory in visible text and inside OSC-8 hyperlink targets;
the substitution is length-preserving, so every column and every escape payload
is byte-identical. Four benchmark scripts defaulted to a private scratchpad that
existed on one machine and no other — they default under $HOME now. A private
host name, a provider's internal pod address and four person-specific comment
examples go the same way.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* the transcription door no longer cites a package that is gone

internal/voice held v1's microphone recorder and its own transcription client,
and nothing imported it any more, so it went. Four comments and one design
document still described it in the present tense — MULTIMODAL.md said its
machinery "is real and waits on a surface wave", and transcribe.go cited
internal/voice/transcriber.go as the live source of the wire shape it mirrors.
The shape is unchanged and transcribe_test.go is now the only thing pinning it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* two documentation lines outlived what they pointed at

JOURNEY.md's catalog used to be an index of scripts as well as a catalog of
journeys; the harness that made it one drove the retired v1/v2 surfaces and went
with them, so the page now says that internal/e2e covers selected v3 scenarios
rather than one script per row. FIDELITY.md spoke of what "the .dc.html actually
sets" after that export was removed; it is the record of what the design set.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* the change entry for the second public cleanup

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* the last personal paths and the last voice reference, now that their pull requests landed

Thirteen pull requests merged into dev while this branch was being built, which
freed six files the collision rule had put out of reach. internal/provider/
attribution.go still said internal/voice reaches the transcription endpoint on
its own; internal/manual/chat/commands.md taught the slash rules with a real
person's home in the example, and so did internal/tui3/detach.go and
slashchip.go; docs/design/questions/DESIGN.md linked two ideation drafts that
never existed in this tree; and two conversation-runtime records and one
ab-routing ledger carried absolute paths from the machine that made them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* the change entry follows the files that came back into reach

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
… has closed (review needed) (Agent-Field#997)

* tests: the reading beside a turn stops writing into a conversation that has closed

`internal/session`'s load-dependent reds name a different test each full run
(Agent-Field#959). One of them is now held still: five thousand runs of
`TestAPickTakenByTheClockReadsAsProvisionalAndRunsWithNobodyParked` on the Spark
under load failed thirteen times, every one of them as `TempDir RemoveAll
cleanup: directory not empty` rather than on an assertion, and the file left
behind in the directory each time was `told.json` — the delta stamp.

The writer is `Agent.refreshElsewhere`, started from the turn loop as a bare
`go` of its own. Nothing joins it and `Agent.Close` does not wait for it, so it
stamps the conversation's folder after the session has closed — in a test, into
a `t.TempDir()` that is being removed, which reds whichever test happens to own
that directory.

Two changes, one cause. The reading goes through `readBeside`, the one door for
a reading beside the work (sidecar.go exists because four of these each had
their own idea of cancellation; this was a fifth with none). And the stamp is
written in the same locked step as the assignment, refused when the session has
closed — the ask lane's own law about a clock that ran out after the door shut,
said about a reading. That also makes the stamp true: it claims this session's
model was told, and a stamp that advanced on a block no model ever read is a day
of other windows' landings this conversation never mentions again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changelog: the reading beside a turn and the stamp it writes (Agent-Field#997)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* review: the stamp is owed behind the path, the reading obeys its context, and the law reads the tree

Three blocking findings from the architecture review of Agent-Field#997.

The stamp was written under `a.mu` — a stat, a marshal and a file write inside
the lock a steer, a cut, a named interruption and every drain take before a
request leaves. That is the shape Agent-Field#876 lifted out of the meta stamp, and the
≤50 ms law cannot see it because `paceAgent` never sets `Place.Dir`. It is owed
under the lock and performed behind it now, through a `stampWriter` of its own
that `Agent.SettleWrites` settles: the owe is registered while the session is
still open, which puts it ahead of `closed` and inside the settle `Close`
already performs. The closed check moves up to the reading's first acquisition,
so a closed session does not walk the index at all.

The `readBeside` ask discarded its context, which left the goroutine exactly the
lifetime the deleted bare `go` had while three comments and the change entry
claimed it was cancelled with the turn. The context is threaded and obeyed
before the walk and again before the assignment, and `tellsElsewhere` is asked
at the call site so a task node's turn enrols no no-op reading in the watch.

The test pinned the early return rather than the shape. `Owe` starts its
performer at once, so "the file is not there yet" is a race with that goroutine
and cannot be a fixture: where the call SITS is the property, and
taskdelta_law_test.go reads the tree for it, with both the shape it refuses and
the shape it asks for planted. The runtime half now holds the reading on a
channel through a real `Close` and settles before asserting the negative.

Also: `NoteTold` only moves forward, because two readings written behind the
path can land out of order; and the entry no longer claims the stamp is written
where what it claims becomes true — delivery is at the drain's
`landVolatileLocked` and `elsewhereTold` is never persisted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* tests: a fixture that owns an agent settles what its reading owed

Moving the stamp behind the path moved the fixtures' obligation with it. Three
hand-built agents in taskdelta_test.go call the reading directly and nothing
ever closes them, so the write they owed was left to land whenever — which the
proof run caught at once: 200 runs under `-race` failed as
`TestAProjectWithNoOtherWindowGetsNoBlock … TempDir RemoveAll cleanup: directory
not empty`, the same shape, one level down.

They settle in their own cleanup now, which is the contract `Agent.Close` meets
for a real session and which placemeta.go already states for every test that
reads one of those files back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* review: the reading stays on the law, lands after its turn, and owes the later stamp

Four findings from the confirm review.

The ask was hoisted into a variable, which took `refreshElsewhere` out of the
set the sidecar law watches — that set is read off the tree, and it reads only
the function literal written into `readBeside`'s second argument. It is written
out inline again, inside the condition rather than behind a nil.

The assignment refused a reading whose turn had ended, which is not what the
context is for: `elsewhereText` belongs to the conversation, not to the turn, and
loop.go says in so many words that a read landing late rides the next step.
Dropped, a disk slower than a short turn re-walks from the same unmoved `since`
forever and delivers nothing. The context still stops the reading STARTING the
walk; only `closed` stops the answer landing.

The stamp's coalescing is max-wins on the instant rather than last-closure-wins.
`Agent.Abandon` releases `a.mu` before it cancels, so an older reading can be
owed after a newer one, and a [stampWriter] replaces its patch — the older
closure would have been the survivor and would have written a stamp behind the
block the model was handed. The instant is kept beside the writer under the lock
and only moves forward; the patch writes what is kept.

And the law accepted `NoteTold` inside ANY `Owe`, including the meta stamp's —
which is off the path and also never happens, because the next meta patch
replaces it. It requires the told stamp's own writer now, with that negative
planted beside the other two.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* review: the closed check and the three writes it guards are one swap-shaped hold

Agent-Field#999 lands `Agent.writeIfOpen`, the one door for "write nothing into a
conversation that has closed", and this reading is one of its callers the moment
it is on dev. So the region is shaped for that swap now: the lock, the check, the
three lines it guards, the unlock, and nothing else between them — the prose
moved above the hold and the comment names Agent-Field#999 as what replaces it.

No behaviour changes: the check already sat immediately before the owe, with
comments between.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rs turn bad (Agent-Field#1003)

The lane row's default ran aforge's own chooser on every request, paying
aforge's measurement budget to second-guess a router that balances well
most of the time. Now auto sends the legacy preferences and lets the
router route; a per-model gate counts refusals and unusable answers, and
twice in a short while arms the chooser for a window. The belief ledger
learns from every named lane's answers either way, so a takeover is never
a cold guess. openrouter keeps its meaning as auto without the safety.
…fer (review needed) (Agent-Field#1012)

* provider, cmd/aforge: the last loose locks hold their mutex from a defer

The provider half of the lockdefer burn (Agent-Field#431): forty-seven sites across
thirteen internal/provider files, plus the seven cmd/aforge stragglers,
were the snapshot/test-and-set-then-release idiom with the Unlock on the
success path. Each became a small method that holds the lock from a defer
for its whole body and answers what the caller needs, with the slow or
re-entrant tail left outside. No logic, ordering, or under-lock field
access changed.

That was the last entry on the known-red ledger, so the ledger burns to
zero here: .github/known-red.txt and its ratchet test are deleted
together, as the ruling in docs/rules/ci.md prescribes. The shared
repositoryRoot helper moves to internal/ci/root.go so the remaining ci
tests keep their door.

TestEveryLockInTheGuardedTreeUnlocksFromADefer now passes on a clean
tree, and the full internal/provider, cmd/aforge, internal/guard and
internal/ci suites are green.

Co-Authored-By: Claude <noreply@anthropic.com>

* changelog: the lockdefer burn entry for Agent-Field#1012

* docs, ci: the words stop describing the known-red ratchet that is gone

The burn deleted .github/known-red.txt and its internal/ci ratchet, but
docs/rules/ci.md, the Makefile header, the ci.yml laws comment and a
clause in internal/remote/ratchet_test.go still narrated the ratchet as
live machinery — a constant that no longer compiles. Each now says the
ledger burned to zero in Agent-Field#1012, that an absent ledger skips nothing, and
that the one reading stays so a ledger cannot quietly return. Comment and
prose only; no behavior.

Co-Authored-By: Claude <noreply@anthropic.com>

* provider: the routefirst takeover drain holds its mutex from a defer

e61f57a (Agent-Field#1003) landed on dev after this branch was cut, with one
snapshot-then-release site in routefirst.go's tellTakeover. It became
takeParkedTakeovers, the same drain-in-one-locked-step shape as its
siblings, so the Emits run outside the lock and the rebased tree keeps
the guard scan at zero.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
…, billed arms, cache pin, shaped gate, stale-build sweep (Agent-Field#1015)

* checkpoint: the race's tightening never stands the first mark below half the price

A raced both-yes pulled the first [taking stock] down to the very
boundary the verdict landed on, and a measured planning turn was told
at round three over one issue and two listings — noise the model waved
past, which is what the round-twenty note then inherited. The first
rung now never stands below checkpointFirstRungFloor, derived as
checkpointPrice / checkpointRatio: triage may make the first look
sooner, it may not make it empty. An unraced turn's ladder is
byte-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* journal: billed arms leave their own call lines, and a turn that hopped seals one usage line per model

The measured planning chat's journal summed to $0.789 of a $1.412 bill:
hedge arms and cut retries were banked to the meter through reconciled()
but wrote no call line, so exactly the expensive requests left no
evidence. A billed receipt now writes one, marked arm: hedge or
arm: reconciled — evidence like every call line, moving no total.

And the turn's usage seal named the model latched at the seal, so the
mid-session hop attributed all 31 requests (2.4M input) to the second
model though the first served thirteen. addUsage now keeps the turn's
share per answering model — the same name the bank row carries — and
appendUsage seals one line per model when there were several, the
turn's one wall time riding the first by name so a replay never reads
it twice.

Co-Authored-By: Kimi K3 <noreply@moonshot.ai>

* changelog: 1007 title under the one-line bound

Co-Authored-By: Kimi K3 <noreply@moonshot.ai>

* turn fold: slices of a repeatedly read file point at the file, and the newest stays whole

The measured planning chat read checkpoint.go in ten overlapping slices
and carried all ten, verbatim, through twenty requests: the fold bounded
generic tool-result accumulation but had no notion that slices of one
file are re-readable where they came from. When the foldable region now
holds several reads of one path, each older slice becomes a pointer in
the stub family the prompt already teaches — the read recipe, offset and
limit, that brings the slice back — no copy is filed, and the newest
slice is kept whole. Selection counts a kept slice as buying nothing, so
a pass still runs only when it can buy the whole headroom.

The trigger, target, batch-completeness and frozen-horizon laws are
untouched; bash and every other tool's results keep the filed pointer
they always got. Freshness of a kept slice is the held-read seam's
question, not this pass's: a pointer says the range was read and how to
read it back, never that the file still says it.

Co-Authored-By: Kimi K3 <noreply@moonshot.ai>

* session: a read the conversation already holds answers with a pointer

Held-range ledger (heldreads.go): a `read` fully covered by bytes the
live transcript still carries, against an unchanged file stamp, is
answered with a one-line pointer instead of a fresh fetch; a changed
stamp retires the whole entry, a partial overlap fetches whole, and a
stubbed or folded result drops out of coverage by itself. The read
tool's description prices the round trip it costs, the system prompt
teaches the pointer sentence beside the stub pointer, and the chat
manual quotes the behavior.

Co-Authored-By: Claude <noreply>

* lanes: the cache pin joins the lane chooser's enforced set rather than being dropped by it

* provider: the OpenRouter-takeover gate counts a refusal only when the router's own pick was refused

A narrowed demand's refusal is evidence about our choice, not the router's
default: for the gate to count it arming the takeover from within the
takeover's own demands. shape reaches the door from the one classifier that
holds the knobs (refusalobject.go's Client.refusalObject), and the refusal
door asks it (routefirst.go's Client.noteRouterRefusal, velocity.go's two
refuseLane branches). The answer sides stay shape-agnostic: an answer that
arrived is a verdict about the machine that spoke it, whichever spine chose it.

Measured in a live chat (2026-09-12): takeover armed, every narrowed demand
404'd, each 404 re-armed the gate — four 'Retry 1/2: relaxed the endpoint
filter' lines at ~80k tokens a re-send before the first rung went bare.

* tui3, session: a launch sweep names every live session on an older build rev

The third binary-shadow incident in the repo's history ends with a visible warning instead of 'same old rev' on every screen. The sweep reads presence files (fail-open), freshness from presenceWindow (age, never pid — the file's own law), and the launch gate emits one advisory line through the same noteFacts door the landing keys use. Manual section added to starting-aforge.md.

* checkpoint: a probe pins the first-rung floor against race-at-any-round

* changelog: entries renumbered to the pull request they ship with

* fmt: sweep and law-visit edits through gofmt

* tests: pin the hop's split seal instead of the old one-line shape

TestEveryResponseWritesItsOwnLineWithItsOwnShape names two distinct
answering models in its fixture (the first response falls back to the
latch, the second names vendor/served-model), so the per-model seal
split correctly writes two usage lines there. The expectation now pins
the split — one line per answering model, figures per model, the wall
time on the first by name — exactly the hop case usagejournal_test.go
covers.

Co-Authored-By: Kimi K3 <noreply@moonshot.ai>

* provider: the gate's shape test is a demand, not the ladder's membership

The first cut classified shape through wirePreferences(...).membershipNarrowing()
— the ladder's first-rung question, which counts require_parameters as
membership. Every machine-unmodified ask read as narrowed, so an ordinary
paced refusal (one of the router's own picks queueing) stopped arming the
takeover: gate_e2e_test's TestTwoPacedAnswersHandTheRoadToTheChooser went red.
Shape is now read from the knobs as a DEMAND — hedgeLane, or a lane choice
carrying admitted names — with require_parameters and the ledger's own Ignore
vetoes left outside the gate's question.

* session: restore the offset/limit pin sentence and route held-reads through the one decode door

lawregistry_test.go pins 'page the rest with offset/limit' in the read
description; heldreads.go now decodes with decodeToolArguments like
every other tool; the round-trip sentence is trimmed to keep the lean
prefix under its budget.

Co-Authored-By: Claude <noreply>

* exec/bare: the edit merge sentence owns its whole rule, reclaiming the round-trip-priced read sentence's room

The lean prefix was 62 bytes over on CI. The 'large unchanged regions'
clause restates the merge sentence, so it goes; the held-range round
trip sentence stays whole.

Co-Authored-By: Claude <noreply>

* changelog: 1015-stale-build-sweep surface fixed to the enum it checks

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Kimi K3 <noreply@moonshot.ai>
…-Field#1004)

* e2e: a needle names a key, it never spells one

TestQuestionsE2E has been 14 of 18 red since Agent-Field#933 took the brackets off
every key on this surface. The suite went on waiting three minutes at a
time for `[1] delete it` while the line drew `1 delete it`, and the
untagged gate that exists so this cannot happen (Agent-Field#184) was green
throughout, because it was looking at the half of each needle that had
not moved:

  - nine needles in questions_e2e_test.go were inline literals, which
    the table's gate cannot see at all; and
  - eleven rows of the table spelled `[c] change` in `screen` while
    their `source` said only `change`, so the gate checked the word and
    never the key in front of it.

So a row that is offered on a key now NAMES the key, and one function
puts the two together:

  - tuiWord gains `key`, and [say] returns [tuiWord.spelling] — the word
    alone on a plain row, `keyedWord(key, word)` on a keyed one.
  - [keyedWord] is the one place this suite writes the gap between a key
    and its word. The nine pasted answers in the questions scenarios go
    through it, so `delete it` stays the scenario's word and the `1 ` in
    front of it stays the product's grammar.
  - nineteen rows are respelled onto it: the question grammar's own
    keys, the consent block's two, and the four landing answers, whose
    one-space column internal/tui3's own relanding and papercuts tests
    pin (`a resolve it   n drop it   s tell it`).

And [TestNoNeedleSpellsAKeyTheSurfaceStoppedSpelling] is the law that
keeps it: a go/ast walk of every screen-reading call in this package
refusing a needle-position literal that brackets a key or pastes a
numbered answer onto its word. It reads the table as data and the suite
as source, and it leaves every other literal alone — a sentence the
MODEL wrote is a coincidence, not a source of truth, which is what the
suite's own header has always said.

internal/manual/chat/questions.md said a key is drawn `[1] allow once`.
It is drawn `1 allow once`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changes: the e2e question needles entry (Agent-Field#1004)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* e2e: the chip is a tail, and a letter is the question's only once you aim

The first paid run after the respelling went from 4 of 18 to 7, and the
two families left in it are the same rot one layer down.

THE CHIP LEADS WITH THE QUESTION'S OWN HEAD. `questionChipTail` waited
for `question · alt+a`; the status line draws `? delete the build
directory? · alt+a` (question.go's questionSegment) and spells the word
`question` only where there is no head, or `3 questions` where there are
several. Its `source` was `alt+a`, so the untagged gate was green on it
exactly as it was on the brackets. The row is its own name now: the
tail, ` · alt+a`.

A LETTER IS THE QUESTION'S ONLY ONCE YOU HAVE AIMED AT IT. `o`, `c`,
`x`, `?` are each the first letter of a word people type into the box,
so the block does not take one from somebody who has not yet looked at
the question (questionkeys.go's questionAimKey; the manual says it in a
person's own words). Six scenarios pressed `o` to open a page, the `o`
went into the message box, and each waited out its three minutes for a
page nobody had opened — with `› o` on the screen it printed.

So [aim] is the gesture, spelled once: `↓` then `↑`, because an aim may
not be an answer — `enter` takes the pick and `esc` puts the question
away — and the walk is therefore walked straight back, leaving the
pointer where it was and the hand on the block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* e2e: the page opens on the pointer, so the foot says what enter would send

The room scenario waited for `nothing chosen yet` on a page that had
just opened on `1 postgres`. Since Agent-Field#789 every answer has a pointer the
arrows walk and enter takes, and the page opens where the block's
pointer stood — questionroom.go's own enter path says so — so a page
with answers on it always has one to send. `nothing chosen yet` belongs
to the `something else…` row, which stands after the last option and
carries no key.

So the moment is read the way it now happens: the foot says `answering `
what the page opened on, and it may not also claim nothing is chosen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changes: the whole of what moved, and the three defects under it (Agent-Field#1004)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…oes, and the prefix gate weighs the real belt (review needed) (Agent-Field#996)

* roles: the compaction role is deleted, because no compaction has called a model since the summariser went

RoleCompaction was a priced, described, settings-visible dial wired to nothing.
[Agent.compact] takes `_ context.Context` and makes no model call at all — a
pass is two mechanical rearrangements of text the session already has — so the
row on the Providers tab offered a person a model for a call that never
happens, and TierHigh's patience was derived from a summary nobody writes.

The role, its tier assignment, its description and the settings and manual text
that offered it all go. The high tier keeps every tenant it actually has —
the auditor, the shaper, vision, the repair, the careful part of a division —
each registered from the package that makes the call.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* session: every request says what it is for, and the door is the only thing that spells it

NINE OF THE ELEVEN CALLERS OF THIS PACKAGE'S MODEL DOOR REACHED THE WIRE
ANONYMOUSLY. The guardian, vision, the shaper, the spell-out, the subharness
intake, the run planner, the harness designer, the ceiling's handoff draft and a
saved program's own AI step all called completeWithModel with no
provider.WithCallTag anywhere above them, so the model-call log could not say
what any of them was: 2,309 of the 2,839 untagged finishes in the ten days to
2026-09-10 are this package's, and with them the answer to "what was this build
spending that model on all night".

The tag was a context value a caller could set or forget, and forgetting it is
silent. It is an argument now — clientdoor.go's `callPurpose` — so a call with
no purpose does not compile, and the door is the one thing in the package that
calls provider.WithCallTag. The three callers that did stamp their own (the
turn, the ask tool, the errand ladder) pass a purpose instead, which is one
spelling of one fact where there were four.

AND auxiliary.go's OWN CLAIM WAS THE FALSE ONE. It said callRole was "the one
door all auxiliary provider calls pass through" while ten calls went round it.
It is the one door every ERRAND passes through, which is a narrower and true
claim, and the sentence says so and names what is legitimately not an errand —
vision streams into the room in the person's own turn, the handoff draft is
billed to the turn on the turn's own model, a program's step runs on no role's
model at all.

nohiddenwork_test.go is the law, on the laws gate: a blank purpose fails the
build, a WithCallTag outside the door fails the build, and the walk fails if it
ever stops finding the door.

No behaviour changes. Every call goes to the same model with the same options;
what is new is that its row in the log has a name on it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* tests: the prefix gate weighs the belt a configured machine actually carries

THE GATE WAS POINTED AT A SHAPE NOBODY RUNS. fixedPrefixBudget's own doc comment
has always said it bounds "the belt the shipping conversation door assembles".
The fixture under it was v3ShapedAgent: a conversation with no memory store, no
accounts hub, no standing items and no saved programs — eighteen tools, 39,073
bytes, eight kilobytes of headroom, green every day.

A machine somebody has finished setting up carries twenty-three tools and weighs
53,025 bytes, which is 5,025 OVER the 48,000 cap the gate was enforcing. It has
been over for as long as the shape existed and the gate could not see it, which
is Agent-Field#576's shape exactly.

The gate now weighs beltShapes[0] — "the shipping conversation, fully wired",
the same definition prompt_belt_test.go uses, through one new helper so the two
cannot drift apart again.

AND THE FIGURE BECOMES A RATCHET. "The measurement plus a tenth" was right when
the number came out of a diet that had just been paid for. This measurement is
not the end of a diet; it is the first honest weighing of a prefix that had
never been weighed, already past what the last diet aimed at, so a tenth on top
would be five more kilobytes nobody chose. It is the measurement and nothing
else, and anything that grows the shipped prefix now fails the build.

WHAT IS OWED IS FILED, NOT FIXED. 48,000 stays as the stated target and the test
prints the 5,025 shortfall on every green run. The bill is one tool: `stand` is
9,607 bytes, more than a quarter of the whole tool block and nearly twice the
next heaviest. Trimming a schema is a change to what the model is told, not to a
byte count, so it belongs to whoever owns the standing belt rather than here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changes: the auxiliary inventory entry (Agent-Field#996)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* replay: the tag law reads the door, because the door is where a tag is stated now

TestEveryTagTheBuildWritesResolvesToARoleSomebodyDeclared walks the tree for
provider.WithCallTag. internal/session has exactly one of those now — the relay
line inside the door — so the law was reading a variable it could not resolve
and finding fourteen tags for a table of thirty-seven.

It reads the door's own call sites instead, which is the same thing the build
does: the purpose argument is what reaches calllog.Record.Tag. The
`callPurpose(...)` conversion comes off before the argument is read, a role worn
as a purpose resolves to internal/roles' vocabulary (over-approximated, because
this law is safe answering with more tags than one site writes and holed
answering with fewer), and the door's own constants are read from their
declaration the way roleWords already reads internal/roles.

AND IT IMMEDIATELY FOUND THE TWO CALLS THAT HAD JUST BEEN GIVEN NAMES. The
ceiling's handoff draft and a saved program's AI step now write tags, and
nothing priced them: both are lane.RoleAuxiliary and both have a row. The draft
rung is the dearest side-call on the ceiling road and it has been invisible to
every reading of calls.jsonl until now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* manual: the roles table stops listing a role the binary no longer registers

The models-and-cost page's roles table is described on the page itself as
'built from what is registered in the running binary, so it is the truth about
this build'. It listed `compaction`, which nothing registers any more, and the
crew's careful line and its account of what aforge calls on your behalf both
named the summary a compaction keeps — a call that has not existed since the
summariser was deleted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prefix gate: the budget is the widest machine's, not the one it was written on

The first spelling of the ratchet was 53,100 — the laptop that weighed it said
53,025 — and it failed on the runner that proved it, at 53,132. The prefix is
not the same size everywhere: `grep` says a longer sentence about itself where
ripgrep is absent, which is 134 bytes on every request of every turn.

So the gate weighs what the WIDEST machine pays. bare.WidestGrepDescription is
the one place that knows which of the two sentences that is, and widestBelt
swaps it in wherever the gate runs, with a law that fails if the tool it names
ever leaves the belt — otherwise the budget would quietly get easier.

The residual is the shelf: load_capability lists the groups THIS BUILD has, 27
bytes more on a machine that can edit video. That is filed in the file's head
rather than fixed here, because naming what a build COULD have is a change to
what the model is told.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changes: the prefix figure is the widest machine's

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* roles: a role that stops existing is dropped from the profiles that pin it

Deleting RoleCompaction left the word in every config.json that had pinned it,
and the panel re-serialises the whole `models.roles` string on any change — so
the next time that person moved ANY OTHER pin the write came back `"compaction"
is not a role`, and every role pin on the machine was unchangeable until
somebody hand-edited config.json. The deletion had no reading for what it
deleted.

roles.Retired is that reading: a one-way list of the words this build used to
answer to, with the line that says what happened to each. It is the only memory
the build has of them, and without it a dead word is indistinguishable from a
typo.

ParseModelRoles drops those keys and says so once per process; writeModelRoles
takes them out of the TEXT, which is what is actually stored, so a person who
changes one pin stops re-saving a sentence about nothing. The test is the exact
string a pre-deletion profile holds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prose: nothing says a compaction asks a model any more

A compaction is two mechanical passes over the transcript; it has never asked a
model. Six comments and two manual lines still offered it as the example of a
billed auxiliary errand — the pocket the title comes out of, the thing the
careful tier is for, a non-streamed call like a harness node — which is a
sentence about a call that does not exist, and was the figure the careful tier's
own patience was derived from until this PR re-derived it.

The settings hint for `careful work` no longer promises it either: what that
tier actually buys is the check on finished task work, the brief a task is
shaped into, and reading an image.

The transcript NOTE a compaction writes is still called a summary in agent.go,
because that one is real.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* roles: a role's word lives in internal/roles, and a law says so

`const spellOutRole roles.Role = "spellout"` lived in internal/session. It
registered, resolved and tagged its call correctly — and reached the cost report
as a word nobody had written down, because roleWords parses internal/roles and
nothing else. roleOf prices an unrecognised tag as a background errand with
nobody waiting, so the ONE auxiliary a person sits and watches was the one
counted as if it did not matter. Nothing failed; a number was quietly wrong.

The word moves to roles.RoleSpellOut beside its siblings, the Register call
stays at the call site, and TestEveryRoleWordIsDeclaredWhereTheVocabularyIs
fails the next one.

And the replay walker stops enumerating receiver spellings. callName flattened
one selector level, so three of the six rows in that switch —
`p.agent.completeWithModel` and friends — rendered as "" and could never match:
the ladder looked complete and was half dead. methodName asks the only question
the law has, which is the method's own name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prefix gate: both arms weigh the shipped shape, at the widest machine

THE LEAN ARM HAD THE SAME HOLE THE FULL ARM WAS REPAIRED FOR. leanShapedAgent
built its own thin config — no memory store, no accounts hub, no standing items,
no saved programs — so the arm that bounds the prefix for the person with the
LEAST room weighed a belt without `stand` (9.6 KB on its own), `remember` or
`search_conversations`, none of which leanCapabilityGroups shelves. It is the
shipped shape on a small window now, which is what its own comment always
claimed.

And three ways the number could go back to depending on who ran it:

  beltShapes[0] read the fullest shape only until somebody put a row in front of
  it. beltShapeNamed asks for it by name.

  WidestGrepDescription returned the fallback sentence because that one is
  longer today; it now measures both and returns the longer, and widestBelt
  ASSIGNS rather than comparing — a swap that only fires when it makes the
  number bigger is a swap that stops firing silently.

  load_capability names the groups this BUILD has, and `edit_video` exists only
  where ffmpeg is on PATH — 27 bytes of prefix that depend on a program nobody
  installed on purpose. loadCapabilityDescription takes the members as a
  question now, so the gate can ask for the widest answer instead of this
  machine's.

Both budget figures are re-measured in the next commit, on the Spark.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prefix: both caps are the measurement, and the three own-client roads say what they are

THE CAPS. Full 53,141 and lean 44,989, both weighed on the Spark against the
shipped shape at the widest machine, both with no headroom, both printing the
shortfall against the target they owe on every green run. PERF.md moves in this
commit, which is the rule for a cap.

THE ROADS. memory_consolidate.go, standing_run.go and tools_doc.go each build a
provider client the one door does not make — a longer timeout, static routing, a
document config — and complete on it directly. That is a real difference, so the
answer is not to force them through the door; it is to make them say the word
the door says. clientdoor.go's withPurpose is that, and it is still the only
file in internal/session that spells provider.WithCallTag.

The two errands this build runs most often with nobody there reached the call
log with NO TAG AT ALL, which made them indistinguishable from a turn that had
lost its name. The standing check is `standing-check` and not `sentinel`,
because cmd/aforge already writes that word for the resident's quorum errand and
two calls under one tag is a reading of neither.

The law now pairs the halves: a file that builds its own client owes a
withPurpose, and it fails if it finds fewer than three such files — a structural
law that matched nothing would pass for ever.

And `compaction` comes out of the replay role table: no build can write it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changes: the four findings the review turned up

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* law: the purpose is required on every own-client call, not once per file

A file-level pairing is satisfied by one road naming itself while the road
beside it stays anonymous, which is the exact shape of the failure this law
exists for: the forgettable one is always the second one.

Every completion in a file that builds its own provider client must now carry a
withPurpose on the context it is handed — inline, or through a local the purpose
was folded into. standing_run.go writes the purpose four wrappers deep and
completes on `callCtx` several lines later, so the reader follows assignments to
a fixed point rather than looking only at the argument.

And the second pass counts the CALLS it judged, not the files: three files that
build a client and nought completions in them would pass in silence.

cmd/aforge-replay's two doc comments stop citing auxiliary.go's deleted
WithCallTag line and point at clientdoor.go's callPurpose, which is where the
tag is spelled now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* roles: the new law found two more of its own kind, and they are fixed

TestEveryRoleWordIsDeclaredWhereTheVocabularyIs caught
`const standingSentinelRole roles.Role = "sentinel"` in internal/session the
first time it ran, which is the second instance of exactly the defect it was
written for and the reason it is a law rather than a note. The word moves to
roles.RoleSentinel; the Register call stays at the call site.

And with `spellout` finally visible to roleWords, the tag law asked
cmd/aforge-replay to say what it prices as — so the table gains the row, which
is spellout.go's own lane.RoleAuxiliary and not a second reading of it.

That row carries the seam it exposes: a person SITS AND WATCHES a spell-out, and
an auxiliary is by definition a call nobody's seconds are being spent on. Either
the lane role or the product is wrong there. The table's job is to agree with
the build, so it does, and says so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* roles: a dead pin is a dead pin, and three more numbers stop depending on the machine

THE RETIRED LEDGER IS DELETED. It was a map of the words this build used to
answer to, so a dropped pin could be told apart from a typo — and it could not
earn its keep. Both are a pin no call will ever consult, both should stop being
written back, and the only reader who can act on either is the person adding a
word right now. Keeping it meant every future deletion owed it an entry, and the
day somebody forgot, the old failure would come back exactly as it was.

So the reading is symmetric: a pin for any word that is not a role is dropped,
the writer refuses only a name being ADDED, and nothing dead is ever written
back. The row DRAWS what is acted on (config.LivePinsAt) rather than the raw
stored text — it used to draw `compaction: some/model` as a live pin while the
list under it had no such line — and the panel says "no longer a role — that pin
is ignored" to the person about to lose it. It is a sentence and not the
log.Printf this had, which was the only one in internal/config and landed on
stderr in every headless and --json door.

AND THREE MORE MACHINE-DEPENDENT NUMBERS. The lean page interpolates the working
directory, so that arm measured 45,034 on macOS against 44,989 on Linux and
failed — a fixture artefact worth tens of bytes in the gate whose entire purpose
is to be one number for everyone. The lean arm was also being handed the FULL
shape's load_capability sentence, making its figure a hybrid of two belts that
neither pays. And the replay table priced `vision` as an errand nobody waits on
while image.go, its only writer, sets lane.RoleTalk with the reasoning beside
it: a look at an image streams into the room during the person's own turn.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prefix: one weighing, one shipped shape, and a debt that is enforced

THE DEBT WAS INVISIBLE. It was a t.Logf, and nothing in the Makefile passes -v —
so the one line saying the shipped prefix is thousands of bytes over what it is
supposed to be was printed where no human and no CI log would show it. The cap
is the TARGET plus a dated waiver now, one per arm in one place, and a waiver
only ever shrinks: known-red's discipline applied to bytes. Growing the prefix
takes a diff with somebody's name on it.

ONE WEIGHING. The two arms were forty lines each, written twice, and the copies
had already drifted — only one printed its shortfall, and it was the arm with
the smaller debt. reportPrefix is called twice.

ONE SHIPPED SHAPE. v3ShapedAgent WAS the second opinion: its own thin config,
eighteen tools, weighed by four gates including both budgets. It is
shippedShapeAgent now. beltShapes' lean row built a third config again, so the
belt law and the prefix gate were measuring different lean conversations under
one name; both call buildShippedConversation.

ONE VOCABULARY READER. purposeWords and roleWords were the same function with a
different path; they are constWordsOfType, read once, with the empty-result
panic inside it. The role law catches the CONVERSION spelling too —
`roleRepair = roles.Role("repair")` was invisible to it — and now also reads
every roles.Register argument, which is the spelling that cannot be worked
around. roles.RoleRepair is declared with the others.

And the manual stops teaching a summarizer rung, its `session: summarizer
returned nothing` string, and a focus appended to its instructions. None of that
exists: a pass stubs and folds, asks no model, and never folds your own words.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prefix: the lean page is weighed the same on every machine, to the byte

The working directory was a fixture artefact worth tens of bytes; the
Workstation line is runtime.GOOS/GOARCH and worth one, which a ratchet with no
headroom fails on just as hard. Both are normalised at the one place that needs
them to be, and the product still tells the model the truth about the machine it
is on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prefix: the lean waiver shrinks on its first run, and `repair` gets a price

The lean figure went 44,989 → 44,920 because the page's working directory
stopped being a fixture artefact and the lean arm got its OWN shelf sentence
instead of the full belt's. That is sixty-nine bytes off a number that had been
measured on a hybrid, and the waiver comes down with it — which is the whole
behaviour the ledger exists to have.

And `repair` reaches the replay table. It only became visible there when the
role stopped being conjured at its call site as roles.Role("repair"): a word
spelled that way is invisible to every reader of the vocabulary, which was the
defect, and the law that now catches it found this the moment it could see it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* changes: the review's findings, all of them

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* prefix: the lean waiver shrinks again, to the byte the page now measures

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* roles: the registry is the tier table, and the vocabulary is a different question

A REGRESSION I INTRODUCED, CAUGHT BY THE SUITE. Making the read drop any word
the REGISTRY does not know threw away `imagegen:paint/model` — a real pin doing
real work. A role gets into the registry by registering, which is how it gets a
tier, and a role with no tier never does: a painter is chosen by a pin or not at
all, since a chat model in tiers.high is not a statement about painting. So the
registry was never the answer to "what are the roles".

roles.Vocabulary is that answer and roles.Known is the reader's door to it. The
list is hand-written, which is a thing that falls behind, so a law parses the
file it lives in and fails when a declared role is missing from it or a listed
one is not declared. The refusal lists the vocabulary too, so a person is shown
`imagegen` as a name they may pin.

And the retired-pin test seeds the row the way a profile written before the
deletion holds it — straight into the file, because the writer is exactly what
would refuse it today and that person never typed it today either.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* session: the two holding actions name the issue that deletes them

The `standing-check` rename and [widestBelt] are both measurements around a
problem rather than fixes for it, and both are deferred to a cross-package wave
rather than grown here. Each now says so where a reader meets it, and names
issue Agent-Field#1010 (spine: Agent-Field#928) as the place it is deleted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* config: whether a pin was already there is a question about the person's file

writeModelRoles forgives a retired word it FINDS and refuses one being TYPED,
and it asked parseModelRoles which of the two it was looking at. That reader
drops every retired word by design, so the stored row it handed back could never
contain the one word the check existed to find: a name that had sat in the file
since before the deletion read as a name typed for the first time, and a machine
with an old `compaction:` pin could not save a change to any other pin.

The set is read off the stored TEXT now — storedRoleWords — because every reader
above that line drops what it does not recognise, and the dropped word is
exactly the word this question is about.

The asymmetry gets its own test: the same word, forgiven when found and refused
when typed. The old test only ever typed a word that was never a role, so the
half that broke was the half nothing watched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* session: a held-reads pointer sentence pays 150 bytes on both prefix arms (Agent-Field#1015)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gent-Field#1018)

* tui3: the draft kill ring — whole-box clears keep the words, and the ↑ walk visits them dim in front of the sent history

* tui3: /drafts, the page over the kill ring (enter restores, d lets one go)

* changelog: the draft-page entry uses the PR's own number

* tui3: /drafts takes its place under /compact and has a fate on home
…to OpenRouter unpinned, exactly the named provider pinned — is the row this build ships (Agent-Field#1019)

`simple` is the default routing row: no pin sends no provider object and OpenRouter's own routing answers; a pin sends exactly {only:[X], allow_fallbacks:false}. The routing row reaches every client this process builds; a pin is refused by the wire, not by a saved memory, and the person is told in the conversation; the pin rides the calls a person is reading and every call of a command they typed; the call log names what each attempt carried; the picker predicts no machine where nothing chooses; a stall under simple without a pin is reported, never rescued. latency, price and off remain opt-in.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv
… still queued (Agent-Field#1024)

The hand-over press wakes a turn that drains the steering queue and, if it finishes, hands unsettled nodes back; two tests read the queue between those two events and saw it shrink. They now count what the model was told, queued plus drained, and hold the turn open so the press under test lands while the model is still deciding. No production change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv
…tall (Agent-Field#1021)

* docs: a README that sells the chat flow and tells the truth about install

The README was an install page carrying four curl lines that 404 for anyone
who is not signed in: the repository is private, `scripts/install.sh` is not
on `main`, and the `agentfield.ai/get/aforge` proxy is an unmerged pull
request on the website. It said nothing about the product.

This one leads with what aforge is — a terminal session you talk to, that
reads and edits files, runs commands, hands work to tasks you can walk away
from, remembers, and takes slash commands — and shows a real captured screen
of that loop on the default model. The install section puts the road that
works today first (clone, `make build`, `bin/aforge`), then names both curl
roads and says in one sentence each which is live and which is not. Long
tails — installer flags, the slash-command table, the key table, the tool
names — are folded.

`internal/manual/chat/running-from-the-terminal.md` carried the same four
dead curl commands, so the manual law makes it the same change. Its first
section now says the same true thing; every `## ` heading is untouched, so
the probe table still reaches it.

Numbers appear only where a cited constant backs them, and the two places
shipped text disagrees with itself (`--parallel` 8 versus 32, `--budget`
150,000 versus `--token-budget` 220,000) are left out rather than picked.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs: README fixes from the refutation pass

An independent lane re-ran every recipe in the claims ledger and drove the
real binary in tmux. Three sentences did not survive, and one whole road was
missing.

The permission card was fiction. The ledger "checked" it with a grep that
matched a comment at internal/tui3/consent.go:20 — whose own next paragraph
says the block draws it now. What the surface actually draws is a bordered
block whose header counts ten seconds (config.DefaultConsentTimeout), whose
second choice is the bare word `always`, and which carries `c change`,
`? ask back` and `safe answer`. Replaced with a verbatim capture at 100
columns, and `c` and `?` are now described in the words question.go uses.

`aforge models` was listed as needing no key. It exits 1 with `aforge needs a
model to work with.`; the repo's own manual page already said so at
running-from-the-terminal.md:583. It now has its own sentence.

The first-run quote was the branch nobody sees. firstrun.go:808 picks
`setupConnectWord` wherever browser connect is available, so a fresh reader
never meets `setupKeyWord`. Both roads are now named, folded, with the
condition that chooses between them.

And the gap: "run `aforge` inside a project" never said what that means. A
new section gives the launch order from cmd/aforge/chatv3_layout.go:84 —
`--workspace`, else the git root, else the directory, except in your home
directory or under /tmp where aforge keeps a folder of its own and says so —
names `/workspace` as the door, and says that on a machine with conversations
on it bare `aforge` opens home rather than a chat. All of it was reproduced
in tmux first.

Smaller: `/spend`'s registered meaning carries its ` · alt+3` again, the nav
row gains the Tools anchor, `ctrl+g` and the right-hand column are described
as the code has them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs: the change entry for the README rewrite (Agent-Field#1021)

Five invalidations, because five things a session might remember about this
repository stopped being true: the four dead curl lines as the install road,
the same four in the manual page, the one-line permission card, `aforge
models` as a keyless command, and `setupKeyWord` as the first-run copy.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs: the account tools are named as conditional

The tool-name table listed the five Gmail and calendar tools and the four
Slack ones with no condition, which reads as "Gmail is on the belt". It is
not: familyTools (internal/session/tools_connect.go:438) hands out the Google
five only for a connected Google account and the Slack four only for Slack,
and connectcaps.go:57 holds the same two sets as the inverse. The conditions
paragraph under the table now says so and names the door a person uses,
`/connect` (internal/tui3/commands.go:78).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…ire will ask for, a routing change lands now, the debug pin records bodies, enter unpins (Agent-Field#1025)

The status chip, the settings lane row and the picker read the pin the transport will act on (provider.PinNow) instead of the profile row, so a retired pairing draws auto with its reason and never @x over a bare request. A routing change in the settings sheet re-installs the row and reaches the very next request because the profile door hands no static routing down. AFORGE_DEBUG=1 takes the in-process road like --debug and writes request bodies. In the lane fold, enter on the machine in force unpins it and typing filters that model's machines. Closes Agent-Field#1022.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv
…hat drew it, and the opened step shows the prompt (Agent-Field#1026)

The generate_image row draws the file it is about in primary ink and the image model that actually drew as a dim qualifier, read from the tail of the tool's own result line (", generated on <model>") so the row and the request cannot disagree; an unknown model adds nothing. Opening the step leads with the prompt, one dim line per other input, then "drawn with X" or "asked for best · drawn with X", then the picture. view_image rows gain their file the same way.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv
…ands every engine down (Agent-Field#1000)

Home's foot box is a block of one height — three rows, padded below the draft so the caret stays put — and the floor is spent only from frames that have the rows to spare, through one door the chat's foot and every place's frame ask. `aforge engine --stop-all` names each workspace it stands down. Gate re-run on Spark against dev 0738312 merge: laws, pr-ready (tui3 312 s, cmd/aforge, enginehost) all ok; driven captures at 120x40 and 80x24 match dev.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv
…e behind a model is provider (Agent-Field#1027)

Owner ruling 2026-09-14 (Agent-Field#1023 item 1): everywhere a person reads, the thing behind a model that answers a request is a provider — the settings row, the /model hints (→ providers), the fold sentences, the rescue and stall notices, the config hints, and the manual page titled Providers. Code identifiers, config keys (lane.talk), the @morph chip and the /status --json `lane` key (a script contract) keep their spelling. A law test fails any tui3 string literal that says lane.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv
…nt-Field#1033)

* PERF.md: the prefix budget table says the caps the gate enforces

The waivers were raised by 150 on each arm in the commit that made them, with
the reason in the code comment, and this table was never opened — which is the
one thing the performance law forbids: a cap that changes changes the doc in
the same commit. The table now reads 53,291 and 45,066, over the targets by
5,291 and 13,566. Closes Agent-Field#1030.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv

* docs: change entry for Agent-Field#1033

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…when you come back to the tab (Agent-Field#1036)

* session: a card for a decision you already made is not asked again when you come back to the tab

A turn's backlog is every event that turn has sent, kept so a surface arriving
mid-turn reads the work from its first line. A CARD in it is the one event that
is not a report of something that happened but a question about something that
has not — and the replay handed it over verbatim, whatever had since been
decided. So a person who approved a task, looked at another tab and came back
was asked to approve it again, on every return, for as long as that turn ran;
and because a question takes the keyboard where it is drawn, the conversation
underneath it could not be scrolled while it stood. Both symptoms, one cause.

The replay now consults the answer. [eventHub.attach] is handed what is still
being asked — the banked words, read off a.mu at the moment of the attach, which
is where a question goes on the book when it is raised and comes off it the
moment it is answered or withdrawn — and leaves out a card whose question is no
longer one. The backlog stays a faithful log of the turn; what is filtered is
the REPLAY. [questionAsked] names the question a card put in front of somebody,
in the lanes' own keys, for consent, a task proposal, a standing card, a harness
offer and a connect ask alike.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv

* session, tui3: the card comes back with your answer under it, not with the question again

The first half of this change left the settled card out of a turn's replay
altogether, and that traded one lie for another: the surface reads a propose_task
call whose card never arrived as a call that was refused (task.go's
[app.refuseFormingCard]), so coming back to the tab said `not started · the call
was refused` over work that was running.

So the engine states the outcome instead of the replay swallowing the question.
[taskWait.decided] restates the proposal with the answer stamped on it the moment
anybody settles it — a person, another window, or the countdown — beside the
restatement [taskWait.withdraw] already made for the other ending, and at the one
place both roads pass through. A card that states its own outcome is not asking
anything, so the replay keeps it and leaves the open one out.

The surface draws it as what it is: the assignment with the answer under it and
no question raised. [taskVerdict] is the one reading of approved-and-redirect
that the window whose key answered and the window replaying a decision both take.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv

* docs: the change entry for Agent-Field#1036

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182eyxXP8Xe7ADNKpYDe4wv

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…he same turn carries on (Agent-Field#1037)

* approval: let account discovery reach its own question

The shipped prompt blanket put approval questions in front of both account
discovery and the connect card. Account listing now lifts as a read, while the
connect tool lifts because its own card is the one consent question; named
rules, deny, and the existing floors still win.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* session: carry account connections through the same turn

Connect answers used to collapse refusal, silence, and typed instructions into
one no, while the tool description told the model to wait for another turn.
Answer provenance now survives to distinct sentences, one shared instruction
says to continue on the next request of this turn, and the belt teaches the
conditional discovery path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* tui3: settle browser waits when their turn ends

A browser row could keep waiting and animating after its turn had closed, and
words typed beneath a browser question opened a key-check card. Turn settlement
now closes those rows with the existing incomplete wording, and only typed-key
questions can open the check card.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* session: hide browser sign-in exchange details

Browser callback failures used to pass their raw exchange text, including a
state nonce, into the transcript and tool result. The session boundary now
keeps vendor refusals in plain words and replaces internal exchange failures
with one honest, non-sensitive sentence.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* manual: tell the truth about account connections

The manual said the browser stayed closed, concurrent credential writers could
lose a change, and account bootstrap tools followed the ordinary approval path.
It now describes the opened browser and retained address, locked store, single
connect question, same-turn continuation, and the distinct ways a question can
finish.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* session: let a connect answer beat the clock

The five-minute branch could call an answer silence after its resolver had
already claimed the question. The clock and resolver now share one atomic
winner, and a claimed answer is returned even when its send is still in flight.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* connect: hide every failed browser exchange

The session hid familiar OAuth failures, but unknown text passed through and
the Connections tab still drew raw callback errors. Browser failures now cross
one deny-by-default boundary; only a short vendor-shaped refusal is retained.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* session: prove account pickup on the shipped posture

The same-turn acceptance ran under blanket allow, where its zero-consent claim
could not fail. It now runs under the shipped prompt posture and proves the
connect card is the only question before the newly armed tool runs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* manual: keep account answers inside the search window

The privacy heading traded away the old asker's words, the SearchBoth guard was
rewritten into a plain search, and the MCP inventory was split under false
counts. Both vocabularies now retrieve, the rescue direction is loud again,
and the original 28-row section is whole.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* session: the account cue pays for itself out of what was said twice

The new account sentence and the same-turn wording pushed both prefix arms 79
bytes over their caps, and the sentence named `services` without the belt fact
claiming that name. The fact now lists both tools it spells, says only what has
to be true before the call, and `use_service` no longer repeats the ordering
the fact already gives — leaving both prefixes below where they were on dev.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* changelog: the connect-on-demand entry for Agent-Field#1037

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…e keystroke (Agent-Field#1039)

Home's ctrl+e writes the archive flag and then re-reads the world on the spot,
so that the row moves under the hand rather than on the next sweep. The seam it
re-read through answers from what is held and refreshes behind itself, and the
write went straight past that cache to the engine — so the rebuild redrew the
row exactly as it was, and the row went only when a later beat's fetch had
returned and a later beat rebuilt. Two seconds of allowed staleness plus up to
two three-second beats is the several seconds a person saw between pressing the
key and watching the row go.

hostWorld.archive is the seam now: the write over the wire, then the held copy
corrected and the entry aged out so the next reading still asks the engine what
it really thinks. That is hostStanding.save's correction, which already existed
for the ambient side, applied to the one write home makes against the world. A
refused write changes nothing here, and bringing a row back is the same
correction in the other direction.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
ZeroPoint95 and others added 29 commits October 13, 2026 22:28
…eld#1819)

* fix: price qualified shell models on their selected service

* docs: record qualified shell model pricing for Agent-Field#1819
…Agent-Field#1820)

* fix: validate consistency findings and retain partial review coverage

* fix: keep partial posting payloads honest across legacy and advisory reports

* docs: record review validity and partial coverage for Agent-Field#1820
* fix: read complete bounded catalogs when connecting providers

* changelog: record complete catalog connections for PR1822
* changelog: roll up v0.8.0 from current dev

* changelog: the v0.8.0 rollup own entry for PR1821

* changelog: include complete provider catalogs in v0.8.0 roll-up
…eld#1823)

* test: drain learned-quirk writers before simulating a restart

* changelog: record the restart fixture ownership repair
…ield#1824)

* test: drain learned-quirk writers before simulating a restart

* fix: serialize learned-provider memo snapshots through replacement

* changelog: record the restart fixture ownership repair

* changelog: record ordered provider memo persistence
…eld#1825)

* changelog: reconcile v0.8.0 with the merged restart repairs

* changelog: record the v0.8.0 reconciliation PR
…ps a leading fence (Agent-Field#931) (Agent-Field#1807)

* chat: one reader for a report's first prose line so every surface skips a leading fence (Agent-Field#931)

A report that opens with a code fence used to draw three backticks on the
tasks table, the home panels and the task record, while the landed card
(fixed in Agent-Field#889) already quoted the sentence. The cause was two readers: the
surface skipped the fence through firstProseLine, but the engine wrote
TaskIndexEntry.Outcome through taskOutcome, which read the literal first line.

Lift the fence-marker detection and the first-prose-line reading into one
leaf package, internal/reportline, that both the surface and the engine
import. taskOutcome, taskFirstSentence, switcherFirstLine and the renderer's
mdFenceOpen all route through it; firstProseLine becomes a thin wrapper. A
structural law pins that every path quoting a report's first line goes
through the one reader, so a future hand cannot reach for firstLine and put
the fence back.

* chat: change entry for the one-reader fence fix (Agent-Field#1807)

* chat: drop duplicated test table and merge the law's two AST helpers (Agent-Field#1807)

firstProseLine is now a one-line delegate to reportline.FirstProse, so the
Agent-Field#889 table in tui3 re-tested the same logic the reportline table already
pins; keep the two card tests that prove the surface is wired to the reader.
Fold the law's bodyCallsSanctionedReader and bodyCallsFirstProse into one
bodyCallsAny(names...).

---------

Co-authored-by: ZeroPoint95 <329227198+ZeroPoint95@users.noreply.github.com>
Agent-Field#1809)

* tasks: pin the tasks-heading test clock to local zone so it is $TZ-stable (Agent-Field#1808)

The window buckets days in the viewer's local zone on purpose (usageBucketStart,
and the "THE DAY IS THE WRITER'S" law on SpendToday). The test built its
fixture clock in a fixed -04:00 zone and asserted the chat manual quotes the
rendered `since aug 11` verbatim, so once that clock was read as local on a
host far enough east it crossed midnight and rendered `aug 12` instead — green
on a UTC runner, red on a UTC+8 box. Build the fixture clock in time.Local so it
agrees with the bucketing; verified identical under TZ from Pago_Pago to
Kiritimati.

* tasks: change entry for the $TZ-stable tasks-heading test (Agent-Field#1809)

* tasks: pin every tasks-page fixture clock to local zone, not just one (Agent-Field#1808)

The same fixed -04:00 fixture clock lived in five tasks-page test files, and the
window buckets days in the viewer's local zone, so two tests already failed on a
UTC+8 box — TestTheManualQuotesBothTasksOpeningHeadingsExactly on 'aug 11' vs
'aug 12', and TestTheTasksPageGroupsByWhatYouDoNext on the 'shift+← aug 2 – aug
25 →' window control. One shared cause (Agent-Field#176's lesson), so fix it everywhere:
build each fixture clock in time.Local. Verified green across the full span of
host zones from Pago_Pago to Kiritimati.

* docs: clarify existing DST limitation in tasks change entry

---------

Co-authored-by: ZeroPoint95 <329227198+ZeroPoint95@users.noreply.github.com>
* fix: ask an ask-here errand's approvals in its own pane

A call inside home's `ask here` errand that the approval policy grades
"ask" blocks inside the errand's session until that agent is answered.
errandEvent had no case for EventConsentRequest, and nothing else holds
the errand's agent, so the errand sat `working` on a question no screen
drew, and a `1` pressed at it went into the follow-up box.

- The pane now draws the approval under the call it is about, with the
  conversation's own question builder and renderer: `1 allow once` and
  `3 deny`. There is no `always` from the pane.
- The answer goes straight to the errand's agent (ResolveConsent), not
  through the block's door, whose receipt lands above the window's own
  box and whose `c change` would be answered by the window's engine.
- The row says `waiting on you` and sorts first; the live block gives
  way while the turn waits; the call's row keeps `allowed`/`denied`.
- The block's settle guard applies to the approval's digits and clicks,
  so a digit typed into a follow-up cannot allow an unread command.
- Approvals are dropped when the turn ends; several in one step are
  asked oldest first. Results pair to rows by call id.
- errandWait is renamed waitErrand so the harness's waiter law sees it
  and a test can hold a gated stream open.
- asking-from-home.md says all of this, and no longer sends approvals
  to `continue as a conversation`, which ends the waiting call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: hold the ask-here card to the question block's guards

Home's `ask here` pane routed its standing card's keys straight into the
block's router, past the guards the block keeps in front of it.

- While a correction was being typed after `o`, the card still owned
  `1`, `3` and `0`: "make it 10 tomorrow" answered it yes at the `1`,
  set the reminder up as first proposed and lost the rest. Every key is
  text while the change is written now.
- The card took a key or a click the instant it appeared. It now keeps
  the block's settle guard, counted from the first frame that drew it.
- Its answer went through the block's door, which files a receipt above
  the window's own box, in a conversation that never asked. A question
  marked `elsewhere` leaves no receipt and counts no yes.
- asking-from-home.md says all three, names the change key `o` (it said
  `c`), and two probes pin the asker's words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* changelog: ask-here pane approvals and card guards (Agent-Field#1833)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* changelog: keep the Agent-Field#1833 entry title under 100 characters

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: a correction owns every key, and the card re-arms after an approval

Review of Agent-Field#1833.

- While a correction is being written after `o`, the box owns every key,
  approval included. With a card and an approval up together, "make it
  10" allowed the call at its `1` and left "make it 0" in the box.
- An approval arriving zeroes the card's settle stamp, so the card's
  answers settle again when they come back. A `1 1` allowed the call
  and set up the reminder in the same instant.
- The routing comment names the change key `o`, not `c`.
- The manual's run-on heading is two sections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…do (Agent-Field#1834)

* fix: make home's ask-here hints and the /help digits name what the keys do

- alt+enter on home belongs to the router (the composer layer); drop the
  unreachable alt+enter arm from home's ask-here case and keep ctrl+enter.
- An errand row's foot says `enter or → answer this ask here` (and
  `enter answer this ask here · esc clear` over a draft); tab on the row is
  the next place.
- The pane's `tab or esc back to the list` stays the last clause, so a
  60-column frame keeps it; `/ commands` is not named while the pane has
  the keyboard.
- /help numbers each place (`1 home · 2 AI teams · …`) instead of calling
  placeOrder the tab bar's order.
- The manual pages say the same: ctrl+enter vs alt+enter, the row and pane
  feet, and which digit opens which place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: give the ask-here pane's box its own words, and raise its sheet on a phone

- While an errand's pane holds the keyboard, the box under it says
  `type a follow-up` (or `type the change` after `o` on a card) instead of
  home's `type to search or start something new`.
- On a phone-width window an errand's sheet now follows the pane's focus,
  so `ask here`, its chord and `→` on the row show the box the keys type
  into; before, only `enter` raised it and typed letters went nowhere visible.
- The phone sheet's box draws the same sentence at rest.
- Manual: the pane's box, ask here on a phone-width window, and the card's
  correction key (`o`, not `c`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: home's arrows never cross columns; say what → opens instead

- keys.md, home.md, commands.md and places.md said ←/→ cross home's
  columns. Since 2026-09-17 every stop is in the field's one column and
  the rail is never walked: → opens the row's verbs, ← closes them, and on
  an ask-here row → hands the pane the keyboard.
- The strip's words now match the code (x delete, p pause, s stop it), and
  the project row's `its chats` verb (removed in Agent-Field#1422) is no longer promised.
- The phone inbox's folded project opens with → and folds with ←.
- Comments in home.go, placekeys.go and verbstrip.go no longer cite the
  deleted homeView.crossColumns.
- A truth test fails if any section repeats the crossing claims; three probes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: home's ctrl+e asks to delete, it does not close a tab

- keys.md said ctrl+e closes, archives and reopens a conversation, that
  the strip's verb is `x close`, and that the card legend says
  `ctrl+e close`. Since Agent-Field#1750 ctrl+e on a conversation row opens the delete
  confirmation (legend `ctrl+e delete`), and enter reopens a dimmed row.
- homeArchiveRow's comment says no key reaches it; tests still use it to
  make closed rows, so it stays.
- A truth test fails if a section repeats the old claims; one probe, and
  the places heading for the box's rule gains the asker's words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* changelog: entry for Agent-Field#1834

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* review: /help's digit row in commands.md, the o key, and leftovers

- commands.md quoted /help's old `established shortcut order` row; it now
  quotes the numbered list, and a truth test refuses the old phrases.
- asking-from-home: the way back is the last clause except while a change
  is being typed after `o`.
- Comments call the correction key `o`, and the ctrl+x comment no longer
  says → crosses columns.
- Remove the e2e rig's unused altEnter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: let the pane's card settle before the box-sentence test presses o

Agent-Field#1833's settle guard drops a key that lands with the card, so the test pins
the clock and moves it past questionSettle once the card has been drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…nd watches (Agent-Field#1831)

* automations: the design, and the core — schedule, store, presence, clock

The design (docs/design/automations/DESIGN.md) replaces standing items and the
v1 scheduler with one mechanism: a schedule, an optional look, an action, run
only while a codeaf window is open. audit-notes/standing-and-schedules.md is the
evidence it answers.

internal/automation is the object and its machinery, with nothing wired yet:

- schedule: five-field cron read in the automation's own zone, stepping in
  absolute time so the wall clock never goes backwards (a 01:30 line runs once
  on the night the clocks fall back); intervals on an anchored grid, so late
  runs never drift the next one; lines that never match are refused.
- store: SQLite (WAL) with the person's half as a document and the clock's
  state as guarded columns; a slot becomes a run in one transaction and can
  never be taken twice; a change counter every window reads from.
- presence: one OS lock per open window, so "is any window open?" is answered
  by the kernel, not a heartbeat.
- clock: one holder at a time, catch-up once and marked late, one run per
  automation at a time, two pieces of work at once, watches that speak on the
  change to yes, explicit outcomes read from reports and context causes, and a
  clean stop when the last window closes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the engine side — the automation tool, its card, and the runner

- `automation` (propose, list, pause, resume, delete, run, history) is on a
  conversation's belt when a store is behind it, and never on a task's or a
  run's: nothing an automation does may arm another. Every answer ends with
  the time.
- The card is one question kind (`automation`) built once in the session:
  1 Save · 2 Save and run it now / check it now (not for reminders or worktree
  work) · 0 Don't save · words are a correction. It shows the schedule in words
  and exactly, the first run, and a watch's estimated daily cost when the price
  is known. Save and run it now hands the action back to do in this turn, so
  approvals reach the person and "always" is banked for later runs.
- The runner looks (a command with the provider keys stripped, a bounded file
  listing that says what changed since the last decided look, or a tool through
  the person's own gate with its connected account put to use first), judges
  every look on the low-tier seat and bills it to the usage ledger against the
  automation, and runs work as a session built from the person's own config:
  their approval rules with nobody to ask, the first refusal for want of the
  person stopping the run as your call, a money cap, and an outcome that comes
  only from `automation_report`.
- File watches keep a small memo between looks so a change made while codeaf
  was closed is still seen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory always: the store keeps rules as memories marked always

- A memories column, always_on, declared for new stores and added to old
  ones by migrateMemoriesAlways inside one immediate transaction, with a
  partial index over active rules; the owner migration now checks its
  column inside its transaction too, so two opens of one old store at
  once cannot both alter the table.
- memory_always events set and clear the flag; the add and supersede
  payloads carry it, a supersession keeps the retired row's rule, and the
  replay and the sync fold both apply it.
- The write door promotes a remembered row when the same words are asked
  for always, and never demotes a rule.
- AlwaysMemories reads the rules for named owners in one order (person,
  machine, project; oldest first); rules are no longer router candidates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the clock process, window presence, and no timers on the machine

- `codeaf clock` (hidden machinery, like `engine`) is the one process that runs
  automations: it takes the lock or leaves, builds each run's configuration
  through the same assembly a conversation uses (extracted from openV3Launch as
  v3ConfigFor, which finds no conversation and starts nothing), runs keyless
  when there is no key so reminders still work, and retires when its binary is
  replaced and nothing is running.
- Every window holds presence for as long as runSurface runs and starts a
  clock when none holds the lock, checking again every 30s.
- Conversations get the automations door, one store handle per process.
- Every start of this build takes the old launchd/systemd timers (tick and
  wake, both names) off the login, acting only on definition files it finds
  under HOME. `codeaf tick` stays as a hidden verb that does nothing, so a
  timer an older build installed ends quietly until it is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the window side — the card, the run lines, notifications and the store watcher

Every window reads the automations store on a two-second beat: a finished
run draws one dim line in the conversation that made it, the first window
on the machine to claim a run raises the desktop notification, and the
quit question gets its snapshot. Local windows hold presence themselves;
the doors to another machine will hold it there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory always: rules ride every turn and task, /always, the memory place's a

- Session: remember gains always; a rule settles through the one write
  path and lands as a preference; an ordinary line never sees, rewords or
  retires a rule; /always (RememberAlways) asks nothing; AlwaysMemories
  lists the rules in force; a conversation with no project of its own
  keeps its rules for the person and says so.
- The model's own rule is a question: internal/approval's KeepsARule is a
  floor under every allow (and under no policy at all), no memo or
  guardian answers it, its card offers no standing yes, and with nobody to
  ask it is refused in words the model can act on.
- Injection beside the standing orders: an <always> block in message[0]
  (no ages, stable order, 12 rules / 2,400 runes, kept on a failed read,
  lean profiles included), task briefs, plan-born run workers and
  codeaf do; rules skip the binding reads and the memory tidy.
- Wire: Memory.RememberAlways, Memory.Always and Memory.SetAlways.
- TUI: /always and its listing, an always fact on rule rows, a on the
  strip and the foot, and the card.
- Manual: three sections on what-i-remember and the probes that ask how
  to make a rule; PERF.md records the rules block's bounds.
- The fixed prefix is over its cap by 152 bytes on this branch alone; the
  waivers are not raised (the standing deletion pays it back).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: delete the v1 resident's scheduler

The v1 resident kept a scheduler nothing could reach: no surface has made a
charter since Agent-Field#469, and no production code installs its timer. It still ran
through `codeaf wake`, advertised in --help as "run one full background pass
by hand", and doctor read its timer. docs/design/automations/DESIGN.md
replaces all of it; this removes it.

Gone:

- internal/resident: the watch engine and sentinel seam (watch.go), charter
  commands and the timer offer (charters.go), tenure, the practice loop, the
  retrospective's charter proposals and hygiene nudges, and every hook in the
  tick, the quiet gate and the splice (the charter draft on compile).
- internal/store: charter.go, charter_spec.go, tenure.go, standing_watch.go,
  the practice loop's half of practice.go and the dead notebook reads, the
  charter command kinds, the proposal-appetite trait and the "proposals"
  reversal class, and the three charter question categories.
- internal/head: the temporal compiler (standing.go), the charter half of
  question answering (charters.go, now answers.go), rule targets in
  change/stop/recall/open/status, the `standing` belt read, and the money
  rails for standing proposals.
- internal/watchdog, and internal/registry (no importers at all).
- cmd/codeaf: wake's pass, the sentinel client, the doctor rows `background
  timer` and `standing`, and the wiring in resident_build.go.
- config: practice_budget_usd, practice_idle, brief_after and tenure_after,
  their rows, resolvers and env-table lines; the keys are retired, so a
  profile holding one is not told it is ignored.

`codeaf wake` stays dispatched as a hidden verb that does nothing and exits 0,
because a timer an older build installed keeps running it until the first
start of the automations build removes it, and an unknown verb exits 1.

Old stores still open and rebuild. Every v1 event stays in the journal and
replays as an unknown kind; the `charters` table is no longer created but is
never dropped, and nothing reads it beyond a tolerant lookup naming an older
build's work in a self receipt. nodes.charter_id, Provenance.CharterID,
agent_questions.origin_charter_id, the brief's charter item and the practice
rounds' question replay all stay, because removing them is a migration that
says nothing new. A charter question an older build left open lapses on the
next pass, and a queued charter command is refused in a sentence rather than
by its spelling. internal/store/legacy_scheduler_test.go pins both halves.

The resident's own manual loses standing-goals.md and says what happened in
daily-rhythm.md; the chat manual's `codeaf wake` section becomes one short
section with `codeaf tick`, and the doctor section loses its timer row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: over --host and --at — the far machine's store on the wire, and its clock kept for an attached window

A window over --host or --at sits in front of a conversation on another
machine, whose automation tool saves into that machine's store and whose
clock runs only while a window is open there. So such a window now reads
and changes the far machine's automations, and the far clock counts it.

- Protocol 21: thirteen Automations.* calls, one per tui3.AutomationsSeam
  function, answered from the engine machine's store; Welcome.Automations
  and Welcome.AutomationsZone say the engine has them and in which zone a
  rhythm is read; Hello.Window says the connection is a window.
- The engine door supplies remote.EngineAutomations (the store, the zone,
  and keepAutomationsWindow as HoldWindow). A Window hello holds presence
  before it is welcomed and lets it go on every road out; an engine with no
  store advertises nothing and refuses every call.
- hostOptions builds the seam from the client when the welcome says so,
  and the zero seam otherwise. Only the --host and --at boot dials say
  Window; the beside dials and the local engine road never do, which a
  structural law now holds.
- Manual: a section on which machine runs them and when they stop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: the v1 scheduler is gone

docs/STANDING.md opens with a note saying what was removed, what an older
store keeps, and that docs/design/automations/DESIGN.md replaces it; the rest
of the page is left as history.

docs/FEATURES.md loses the entries that described the removed machinery as
working: the timer offer, charter proposals, the practice loop, probation and
tenure, and `codeaf wake`. The entries that only mentioned it (the modality
rail, the retrospective, the arrival brief, curiosity receipts, competence,
doctor and the environment list) now say what the code does. docs/LIMITS.md
drops the practice carve-out row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the demo home seeds automations, not standing orders

cmd/codeaf-demo-home now makes seven automations across its three projects
(two reminders, the morning sweep on a cron line, a dependency bump in a
separate worktree, a command watch on CI, a once-watch on pricing.json, and a
paused one) and replays the clock over a fortnight of open windows, so their
runs carry every outcome, late catch-ups, and run folders that are really on
disk. Three were said in seeded conversations, whose Words are turns those
journals have, so their lines land when those conversations open. The spend
ledger books each run's own cost under UsageLine.Automation in place of the
standing check line, and the package no longer imports internal/standing.

internal/automation gains Store.SetClock: the one door a fixture needs to
write a history through Create, Take, Start and Finish at the moment it
happened. Nothing in the product calls it.

A demo launch, and the hand-open line it prints, set CODEAF_NO_AUTOMATIONS=1,
so no window opened on the demo starts the clock: the seeded work would
otherwise run for real on the person's own key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the place, the typed command and the quit warning; standing leaves tui3

/automations replaces the standing place in the same slot: the list with
each automation's schedule and last run, its history, and → run, pause,
stop, edit, delete and open. The exact typed forms add, edit, run, pause,
resume and delete, and an add or edit ends on a card like the model's.
Leaving the last window with a run in hand warns once.

Home's next panel and since-you-left read automations; ask here keeps
working, re-homed to its own errands folder, with the automation card in
its pane. Every standing surface in tui3 is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the hints teach automations, and the standing words leave the place prose

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the standing engine leaves the session, the doors and the wire

- internal/session: the stand tool, its card, inbox, world section, mark
  and runner are deleted; the belt fact and the page's paragraph now name
  `automation`, and the prefix waivers fall to the measurement
- automation runs borrow the brain read-only, as standing firings did
- the memory tidy rides the clock (automation.Tidy), gated on MachineIdle
- the sweep's fourth rule reaps stale errands and keeps any an automation
  was saved from
- an automation card answered from another window takes every key its own
  card drew (`2` was refused at the doorstep)
- cmd/codeaf: the ticker, the background repair, the standing seam and the
  host's standing cache are gone; the clock carries the tidy
- remote: Standing.* methods, ResolveStanding and the marked submit leave the
  wire; the held kind goes; the surface-door ledger drops to 18
- config: the background-checks row is retired with its key
- run: worker briefs close on the person's rules alone

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: watch names the idea, and the standing purpose goes

- `watch`'s description said lasting checks were `stand`'s, a tool that is
  gone; it now names an automation without naming a verb some belts lack
- the unused standing-check call purpose leaves; the replay tool still
  reads old logs that carry it
- the fixed prefix falls another 8 bytes and its waiver with it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the docs say what was built

- the design doc gains the typed grammar, the → keys, the quit warning as
  shipped, the store's notification claim, the kept `ask here` errands, the
  read-only brain and the tidy on the clock; the watch cost estimate it
  promised was never built and goes
- the guide, the README, FEATURES, LIMITS and the memory docs name
  automations and `/always` where they named standing orders; the README's
  standing screenshot goes with the page it showed
- AMBIENT and STANDING-ORDERS are marked superseded

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the kind's answer row is said to be the superset it is

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the reading says why it is handed its palette

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* e2e: automations replace standing orders in the end-to-end suite

Nothing in internal/e2e imports internal/standing or leans on a standing
door any more, so the package builds once those are deleted.

- The host guard proves the old-timer removal touches only the throwaway
  login: testdata/oldtimers runs RemoveOldTimers as a real program behind
  the guard, and the developer's tick and wake files, both names, are
  hashed around it. The guard also stands in for osascript and
  notify-send, and sets CODEAF_NO_AUTOMATIONS=1 on every launch whose
  scenario does not name it.
- The shared world keeps no ambient store and no standing answers; say
  and drain take none, and decline an automation card if one ever comes.
- The three standing lanes are deleted. TestAutomationsE2E replaces the
  three TestTUIE2E subtests that were about standing orders, with no key:
  ask here ending on an automation card (wide and narrow), and a typed
  reminder said by the clock into its conversation, as a notification and
  on the automations place, then the clock leaving on its own.
- The words table drops the standing rows, respells the ones automations
  renamed, and catches up with home's activity heading, the seven-place
  bar and the Spending tab's per-chat label; testHomeShape,
  testAnswerFromHome and testOneSpendFigure read what is drawn now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the tui3 and session test builds compile again

Three test files still named what the standing removal took away, so
neither package's tests built at this commit and no manual gate in them
could run: notice_test.go proved a retirement event that no longer
exists, and the usage tests asked for a spend subject that is now
SubjectAutomation.

- notice_test.go: the gesture is /automations, which fires
  eventAutomationsOpened.
- usage_ledger_test.go: an automation's run writes its line under the
  automation's id, and the rollup names the automation.
- usage_spend_test.go: the automation row and its subject word.

These are byte for byte the versions 61022e9 carries, so the two
branches agree on them when they meet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the e2e timing notes stop promising a standing pass

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the chat manual says what replaced standing orders

The chat corpus still taught standing orders — /standing, the stand card,
keeping an eye, the OS timer and `codeaf tick` — after automations had
replaced them. The chat answers from these pages alone, so it would have
offered a page, a key and a timer that no longer exist.

- automations.md is new: reminders, scheduled work and watches; the card
  and its answers; schedules and cron; /automations and its → verbs;
  history and what a run came to; where the news arrives; the clock that
  runs only while a window is open, missed runs marked late; cost limits;
  worktree or checkout; the typed /automations forms; ask here; rules as
  memories marked always; the automation and automation_report tools;
  where standing orders went; and what automations cannot do.
- keeping-an-eye.md and standing-orders.md are deleted. Every other page
  that described standing — home, keys, commands, places, screen,
  asking-from-home, the remote pages, models-and-cost, questions, tasks,
  what-i-can-do, what-i-remember, hints-and-tips and the rest — now says
  what the automations code does, quoting its strings.
- chat_test.go: the forty-nine probes that reached a deleted page are
  pointed at the page that answers them now, and fifty-six probes are
  added in the asker's words. The rerun and due-time tests follow.
- truth_test.go no longer imports internal/standing: the standing facts
  leave, and automation.DefaultTime and automation.DefaultUSD are pinned
  where the pages quote them.
- asked.go's wants follow the pages; lawregistry_test.go drops the two
  laws filed against keeping-an-eye; session's manual gate opens an
  automations store so `automation` is checked, and a second gate builds
  a run's belt so `automation_report` is too.
- The e2e due-time subtest still reaches home, and waits for the
  sentence that says where an automation's next time is shown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: internal/standing is deleted

Nothing imports it any more: the session, the doors, the wire, the
config, the manual's truth table and the end-to-end suite have all
moved to internal/automation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: home's tip leads with the command

A home tip says a key or a command first, and the one that taught saying
an automation did not, so home's row broke its own law.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a collection cannot gain a standing item

The kind names nothing codeaf runs any more. A row an older build wrote
can still be found and taken out; the schema keeps the kind so an older
build on the same machine still opens the database.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a conversation switched to is told what it missed

The missed runs were gathered only on a window's first reading, so a
conversation switched to in a window already open never heard them. Now
any conversation that comes to the front is asked about once, and a run
a window has drawn is not drawn twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the manual says when an errand that went nowhere is cleared

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: gofmt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the complexity ratchet holds the automations engine

The ratchet walked the standing ticker and inbox, which are gone; it now
walks the automations clock, store and runner. The run's Work held 25
decisions against a ceiling of 15, so it is split along its own phases:
the run's configuration, the turn watched for the two reasons to stop,
and what it came to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: comments stop describing standing orders as live

Comments in cmd/ and internal/ (internal/standing and internal/e2e left
alone) that still described the standing feature as current now say
what the code does: the automation tool, /automations, `codeaf clock`
and the rules marked always. Historical records are kept, with doc
links to deleted symbols turned into plain text or pointed at the
replacement, and every bracketed link a rewritten comment names
resolves.

Comments only: the token stream of every changed file is identical
outside comments, apart from one stray blank line in effortscope.go's
import block that gofmt removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a run of work stops at the daily spending limit

Standing firings were held to the person's daily limit; an automation's
work run is shaped like a task, which the turn's check passes over, so
it spent past the limit. It now asks before anything is made for it and
reads `your call` when the limit is reached. A watch's looks are not held
to it: each costs a fraction of a cent, and a refused look is news.

The design doc gets back the watch cost estimate, which is built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the suites pass without standing orders

- home settles its phone shape before it builds again; the band read
  that used to do it went with standing orders
- `/automations` has its fates on home: the place bare, a conversation
  for `add` and `edit`, home's own line for the id verbs
- `automation_report` is communication, and both automation tools have a
  folder-hold disposition; `usd` is a fractional argument
- the dead standing fields, the backlog fold, the held kind, a separator
  and three band orders are removed
- tests that still named standing words, `/standing` as a door or the
  standing ladder stamper now read the automations surface

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: ask an ask-here errand's approvals in its own pane

A call inside home's `ask here` errand that the approval policy grades
"ask" blocks inside the errand's session until that agent is answered.
errandEvent had no case for EventConsentRequest, and nothing else holds
the errand's agent, so the errand sat `working` on a question no screen
drew, and a `1` pressed at it went into the follow-up box.

- The pane now draws the approval under the call it is about, with the
  conversation's own question builder and renderer: `1 allow once` and
  `3 deny`. There is no `always` from the pane.
- The answer goes straight to the errand's agent (ResolveConsent), not
  through the block's door, whose receipt lands above the window's own
  box and whose `c change` would be answered by the window's engine.
- The row says `waiting on you` and sorts first; the live block gives
  way while the turn waits; the call's row keeps `allowed`/`denied`.
- The block's settle guard applies to the approval's digits and clicks,
  so a digit typed into a follow-up cannot allow an unread command.
- Approvals are dropped when the turn ends; several in one step are
  asked oldest first. Results pair to rows by call id.
- errandWait is renamed waitErrand so the harness's waiter law sees it
  and a test can hold a gated stream open.
- asking-from-home.md says all of this, and no longer sends approvals
  to `continue as a conversation`, which ends the waiting call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the word stands on the tab bar, between memory and spend

A place that appeared only while somebody stood in it was a room nobody knew
was there. Eight words need 84 columns, so a narrower frame folds spend and
settings behind more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: banners through the terminal, closing pauses, and watches find the key

What the owner's walkthrough of the first build found, fixed:

- A banner is raised whether or not codeaf has the keyboard, so `r` on a
  reminder raises one too. In iTerm2 it is iTerm2's own (OSC 9), in Ghostty,
  kitty, WezTerm and foot the terminal's OSC 777, and clicking it brings the
  tab back. Elsewhere it is osascript with a sound, or notify-send with the
  logo. The first banner on a machine names the sending app once, linked to
  Notification settings. A codeaf-branded macOS banner needs a Developer ID:
  macOS 26 refuses an ad-hoc-signed applet silently.
- A run's line is also said on the message line of home or the place in
  front.
- Quitting never asks. A run closing codeaf cut off is told to nobody and runs
  again, once, when a window next opens.
- A watch's check passes over a model whose service has no key, down to the
  conversation's own model, and names the model and service when none is
  reachable. The clock re-reads the saved key before every run, and follows
  the newest window's environment (a salted fingerprint, never a value), so
  a key exported in one shell and not another no longer decides it.
- The typed form reads `at 6pm`, `at tomorrow 9am` and `at monday 9am`
  without quotes.
- The clock no longer runs the memory tidy, which the memory rework rules out.
- Home's since-you-left whisper no longer says watches run while codeaf is
  shut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the demo's cut-off run is one the person stopped, and the row-zero law starts at 84 columns

A run codeaf closing cut off now picks up again, which the demo's replay of
the rhythm cannot express. Eight words on the bar need 84 columns, so that
is where the bar is promised never to move. The since-you-left whisper says
what happened rather than what landed, which a first look must not claim.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the change entry for Agent-Field#1831

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a run's whole result is read in its history, and its banner carries it

The run under the cursor in an automation's history shows its full report in
ordinary text, and the history opens on the newest run. A banner says what the
run came to and up to 180 characters of its report, without repeating the title.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the review's fixes

- Deleting an automation stops its run in hand: the clock asks whether each
  run's automation still exists, since the delete takes the run rows (and any
  stop request) with it.
- A rhythm of days that would overflow a duration is refused, not wrapped.
- A files watch's walk checks its budget and its run's context on every
  entry, so a rarely matching glob over a whole home no longer walks it all.
- The judge's client is kept per model and account, so a replaced key is used.
- A window's presence file is locked and written before it is renamed into
  place, so a counter can no longer remove a window being opened.
- `codeaf do` reads the rules before its deadline starts.
- A typed id needs four characters, and the refusal says where the id comes
  from. A ~ folder crosses unexpanded and the store reads it as its own
  machine's home, so a line typed over --host names the far machine's folder.
- Each automation keeps its last hundred runs; forgotten and deleted runs'
  folders go, except a folder holding a worktree, whose changes are the
  person's to review.
- A watch's banner says its own line, not what its look saw.
- The old timers' files are removed before their jobs are unloaded, by label.
- Stale docs and comments; the audit note is dropped from the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: the guide's tool table names automation, not the removed stand

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* automations: the conversation can change one in place

The `automation` tool had no op that changes an existing automation, so
"move my water reminder to 5pm" could only propose a second one beside
the first, often a finished reminder left standing in /automations.

- `change` takes an id and only the fields that change, lays them over
  the saved automation, and raises the same card the typed edit does:
  `save this change?`, `1 Save` and `0 Don't save`. Save goes through
  Store.Update, which works a new schedule out from now and wakes a
  finished one-time reminder.
- An id on a card is what makes it a change, so AutomationHead and
  AutomationOptions decide it once for both doors; the typed edit now
  reads its head and answers from session.
- The page tells the model one that exists is changed, never proposed
  again. The bytes were paid out of the tool description's repeat of the
  watch fields; both prefix arms are 22 bytes lighter and both waivers
  fall by that (PERF.md).
- The manual's "Change an automation" leads with asking, and the denial
  that the chat had no verb for it is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* changelog: the conversation can change an automation in place (Agent-Field#1829)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a change's card promises only the next run its save gives

Review of Agent-Field#1829. A `when` re-sent as it was counted as a new schedule, so
the card worked out a next run from now while Store.Update, which only
reschedules on a different moment, rhythm or zone, kept the old one: a
finished watch's card promised a run it never got, and an hourly one's
promised a slot off its grid.

- automation.ScheduleChanged is now the one reading of "a different
  schedule", and the change op asks it before counting a `when` as new.
- A rhythm keeps its stored zone exactly, empty (the machine's) included,
  so re-sending the same `every` does not give it a zone and move it.
- The refusal names title and words too; a change's card says `next run`.
- DESIGN.md says the conversation's `change` raises `save this change?`.
- Tests: the same `when` re-sent, deleted while the card is up, and a
  paused one staying paused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…lback (Agent-Field#1832)

* update: releases come from one repository; retire the former-name fallback

- The updater (Select, TagPublished, Install) and scripts/install.sh no
  longer ask the repository's former name after a 404 from the release
  repository. That name is only GitHub's redirect to the same repository
  (same repository id), so it never held a release the real one lacks;
  asking it could only ever reach a repository created under that name
  later.
- Install always downloads from the release repository, whatever
  repository a caller wrote on the release.
- The former asset name is still tried inside the same release, for
  v0.1.0, the one stable published before the rename.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: record the one release repository for Agent-Field#1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* update: answer the Agent-Field#1832 review

- Drop the stale H10 comment that described the old fallback above the
  helper that now forbids it.
- selectRelease reads the release repository itself and assetURL builds
  every download address from the constant, so no Release field is
  ever an address.
- The fake servers' request lists in the new update tests are kept
  under a lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ore the chat opens (Agent-Field#1826)

* update: a released codeaf installs the newest stable and restarts before the chat opens

- A stable build in a file named codeaf, with automatic updates on, now
  looks before the chat opens (cached a day, otherwise at most 1.5s, and a
  look that got no answer is not waited on again for an hour), installs
  within 20s with a progress line, and hands the terminal to the new build
  with the same arguments. ctrl+c, a slow download or a failure opens the
  build on disk.
- Only that build is updated unasked (update.AutomaticFor): dev, staging,
  rc and source builds, devaf, stageaf and other file names are told on one
  terminal line and the chat's quiet line, and never replaced. Nothing runs
  without a terminal, under CI, or for --once.
- `codeaf update --version <tag>` and `/update <tag>` pin the file at that
  release; a plain install unpins. The pin lives in the install record, so
  a file replaced by curl drops it.
- The chat's countdown is kept as the fallback when the launch could not
  finish, and is now gated by the same rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: record what auto-update on launch changes for Agent-Field#1826

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* update: a finished install says one short line

`codeaf <tag> installed · restart to use the new version`, in the
transcript and the keys line alike, instead of the sentence about
windows and engines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* update: answer the launch-road review

- A launch that runs out of its 20s clock records the release as slow
  (AutoSlow); for a day the next launches leave it to the chat's
  background road instead of starting the same download again.
- The name rule reads the file that would be overwritten, links
  resolved, on every platform; the check decides it off the frame and
  carries it as Available.Automatic for both launch roads.
- A file already holding the release says "is already on disk ·
  opening it" instead of claiming an install.
- Windows Relaunch ignores console ctrl+c while it waits on the child.
- Both spellings of the restart marker are cleared; the download meter
  draws only when stderr is a terminal; a --debug record opens after
  the launch's own update; Linuxbrew is a package manager.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…r silently (Agent-Field#1830)

* automations: the design, and the core — schedule, store, presence, clock

The design (docs/design/automations/DESIGN.md) replaces standing items and the
v1 scheduler with one mechanism: a schedule, an optional look, an action, run
only while a codeaf window is open. audit-notes/standing-and-schedules.md is the
evidence it answers.

internal/automation is the object and its machinery, with nothing wired yet:

- schedule: five-field cron read in the automation's own zone, stepping in
  absolute time so the wall clock never goes backwards (a 01:30 line runs once
  on the night the clocks fall back); intervals on an anchored grid, so late
  runs never drift the next one; lines that never match are refused.
- store: SQLite (WAL) with the person's half as a document and the clock's
  state as guarded columns; a slot becomes a run in one transaction and can
  never be taken twice; a change counter every window reads from.
- presence: one OS lock per open window, so "is any window open?" is answered
  by the kernel, not a heartbeat.
- clock: one holder at a time, catch-up once and marked late, one run per
  automation at a time, two pieces of work at once, watches that speak on the
  change to yes, explicit outcomes read from reports and context causes, and a
  clean stop when the last window closes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the engine side — the automation tool, its card, and the runner

- `automation` (propose, list, pause, resume, delete, run, history) is on a
  conversation's belt when a store is behind it, and never on a task's or a
  run's: nothing an automation does may arm another. Every answer ends with
  the time.
- The card is one question kind (`automation`) built once in the session:
  1 Save · 2 Save and run it now / check it now (not for reminders or worktree
  work) · 0 Don't save · words are a correction. It shows the schedule in words
  and exactly, the first run, and a watch's estimated daily cost when the price
  is known. Save and run it now hands the action back to do in this turn, so
  approvals reach the person and "always" is banked for later runs.
- The runner looks (a command with the provider keys stripped, a bounded file
  listing that says what changed since the last decided look, or a tool through
  the person's own gate with its connected account put to use first), judges
  every look on the low-tier seat and bills it to the usage ledger against the
  automation, and runs work as a session built from the person's own config:
  their approval rules with nobody to ask, the first refusal for want of the
  person stopping the run as your call, a money cap, and an outcome that comes
  only from `automation_report`.
- File watches keep a small memo between looks so a change made while codeaf
  was closed is still seen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory always: the store keeps rules as memories marked always

- A memories column, always_on, declared for new stores and added to old
  ones by migrateMemoriesAlways inside one immediate transaction, with a
  partial index over active rules; the owner migration now checks its
  column inside its transaction too, so two opens of one old store at
  once cannot both alter the table.
- memory_always events set and clear the flag; the add and supersede
  payloads carry it, a supersession keeps the retired row's rule, and the
  replay and the sync fold both apply it.
- The write door promotes a remembered row when the same words are asked
  for always, and never demotes a rule.
- AlwaysMemories reads the rules for named owners in one order (person,
  machine, project; oldest first); rules are no longer router candidates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the clock process, window presence, and no timers on the machine

- `codeaf clock` (hidden machinery, like `engine`) is the one process that runs
  automations: it takes the lock or leaves, builds each run's configuration
  through the same assembly a conversation uses (extracted from openV3Launch as
  v3ConfigFor, which finds no conversation and starts nothing), runs keyless
  when there is no key so reminders still work, and retires when its binary is
  replaced and nothing is running.
- Every window holds presence for as long as runSurface runs and starts a
  clock when none holds the lock, checking again every 30s.
- Conversations get the automations door, one store handle per process.
- Every start of this build takes the old launchd/systemd timers (tick and
  wake, both names) off the login, acting only on definition files it finds
  under HOME. `codeaf tick` stays as a hidden verb that does nothing, so a
  timer an older build installed ends quietly until it is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the window side — the card, the run lines, notifications and the store watcher

Every window reads the automations store on a two-second beat: a finished
run draws one dim line in the conversation that made it, the first window
on the machine to claim a run raises the desktop notification, and the
quit question gets its snapshot. Local windows hold presence themselves;
the doors to another machine will hold it there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory always: rules ride every turn and task, /always, the memory place's a

- Session: remember gains always; a rule settles through the one write
  path and lands as a preference; an ordinary line never sees, rewords or
  retires a rule; /always (RememberAlways) asks nothing; AlwaysMemories
  lists the rules in force; a conversation with no project of its own
  keeps its rules for the person and says so.
- The model's own rule is a question: internal/approval's KeepsARule is a
  floor under every allow (and under no policy at all), no memo or
  guardian answers it, its card offers no standing yes, and with nobody to
  ask it is refused in words the model can act on.
- Injection beside the standing orders: an <always> block in message[0]
  (no ages, stable order, 12 rules / 2,400 runes, kept on a failed read,
  lean profiles included), task briefs, plan-born run workers and
  codeaf do; rules skip the binding reads and the memory tidy.
- Wire: Memory.RememberAlways, Memory.Always and Memory.SetAlways.
- TUI: /always and its listing, an always fact on rule rows, a on the
  strip and the foot, and the card.
- Manual: three sections on what-i-remember and the probes that ask how
  to make a rule; PERF.md records the rules block's bounds.
- The fixed prefix is over its cap by 152 bytes on this branch alone; the
  waivers are not raised (the standing deletion pays it back).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: delete the v1 resident's scheduler

The v1 resident kept a scheduler nothing could reach: no surface has made a
charter since Agent-Field#469, and no production code installs its timer. It still ran
through `codeaf wake`, advertised in --help as "run one full background pass
by hand", and doctor read its timer. docs/design/automations/DESIGN.md
replaces all of it; this removes it.

Gone:

- internal/resident: the watch engine and sentinel seam (watch.go), charter
  commands and the timer offer (charters.go), tenure, the practice loop, the
  retrospective's charter proposals and hygiene nudges, and every hook in the
  tick, the quiet gate and the splice (the charter draft on compile).
- internal/store: charter.go, charter_spec.go, tenure.go, standing_watch.go,
  the practice loop's half of practice.go and the dead notebook reads, the
  charter command kinds, the proposal-appetite trait and the "proposals"
  reversal class, and the three charter question categories.
- internal/head: the temporal compiler (standing.go), the charter half of
  question answering (charters.go, now answers.go), rule targets in
  change/stop/recall/open/status, the `standing` belt read, and the money
  rails for standing proposals.
- internal/watchdog, and internal/registry (no importers at all).
- cmd/codeaf: wake's pass, the sentinel client, the doctor rows `background
  timer` and `standing`, and the wiring in resident_build.go.
- config: practice_budget_usd, practice_idle, brief_after and tenure_after,
  their rows, resolvers and env-table lines; the keys are retired, so a
  profile holding one is not told it is ignored.

`codeaf wake` stays dispatched as a hidden verb that does nothing and exits 0,
because a timer an older build installed keeps running it until the first
start of the automations build removes it, and an unknown verb exits 1.

Old stores still open and rebuild. Every v1 event stays in the journal and
replays as an unknown kind; the `charters` table is no longer created but is
never dropped, and nothing reads it beyond a tolerant lookup naming an older
build's work in a self receipt. nodes.charter_id, Provenance.CharterID,
agent_questions.origin_charter_id, the brief's charter item and the practice
rounds' question replay all stay, because removing them is a migration that
says nothing new. A charter question an older build left open lapses on the
next pass, and a queued charter command is refused in a sentence rather than
by its spelling. internal/store/legacy_scheduler_test.go pins both halves.

The resident's own manual loses standing-goals.md and says what happened in
daily-rhythm.md; the chat manual's `codeaf wake` section becomes one short
section with `codeaf tick`, and the doctor section loses its timer row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: over --host and --at — the far machine's store on the wire, and its clock kept for an attached window

A window over --host or --at sits in front of a conversation on another
machine, whose automation tool saves into that machine's store and whose
clock runs only while a window is open there. So such a window now reads
and changes the far machine's automations, and the far clock counts it.

- Protocol 21: thirteen Automations.* calls, one per tui3.AutomationsSeam
  function, answered from the engine machine's store; Welcome.Automations
  and Welcome.AutomationsZone say the engine has them and in which zone a
  rhythm is read; Hello.Window says the connection is a window.
- The engine door supplies remote.EngineAutomations (the store, the zone,
  and keepAutomationsWindow as HoldWindow). A Window hello holds presence
  before it is welcomed and lets it go on every road out; an engine with no
  store advertises nothing and refuses every call.
- hostOptions builds the seam from the client when the welcome says so,
  and the zero seam otherwise. Only the --host and --at boot dials say
  Window; the beside dials and the local engine road never do, which a
  structural law now holds.
- Manual: a section on which machine runs them and when they stop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: the v1 scheduler is gone

docs/STANDING.md opens with a note saying what was removed, what an older
store keeps, and that docs/design/automations/DESIGN.md replaces it; the rest
of the page is left as history.

docs/FEATURES.md loses the entries that described the removed machinery as
working: the timer offer, charter proposals, the practice loop, probation and
tenure, and `codeaf wake`. The entries that only mentioned it (the modality
rail, the retrospective, the arrival brief, curiosity receipts, competence,
doctor and the environment list) now say what the code does. docs/LIMITS.md
drops the practice carve-out row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the demo home seeds automations, not standing orders

cmd/codeaf-demo-home now makes seven automations across its three projects
(two reminders, the morning sweep on a cron line, a dependency bump in a
separate worktree, a command watch on CI, a once-watch on pricing.json, and a
paused one) and replays the clock over a fortnight of open windows, so their
runs carry every outcome, late catch-ups, and run folders that are really on
disk. Three were said in seeded conversations, whose Words are turns those
journals have, so their lines land when those conversations open. The spend
ledger books each run's own cost under UsageLine.Automation in place of the
standing check line, and the package no longer imports internal/standing.

internal/automation gains Store.SetClock: the one door a fixture needs to
write a history through Create, Take, Start and Finish at the moment it
happened. Nothing in the product calls it.

A demo launch, and the hand-open line it prints, set CODEAF_NO_AUTOMATIONS=1,
so no window opened on the demo starts the clock: the seeded work would
otherwise run for real on the person's own key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the place, the typed command and the quit warning; standing leaves tui3

/automations replaces the standing place in the same slot: the list with
each automation's schedule and last run, its history, and → run, pause,
stop, edit, delete and open. The exact typed forms add, edit, run, pause,
resume and delete, and an add or edit ends on a card like the model's.
Leaving the last window with a run in hand warns once.

Home's next panel and since-you-left read automations; ask here keeps
working, re-homed to its own errands folder, with the automation card in
its pane. Every standing surface in tui3 is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the hints teach automations, and the standing words leave the place prose

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the standing engine leaves the session, the doors and the wire

- internal/session: the stand tool, its card, inbox, world section, mark
  and runner are deleted; the belt fact and the page's paragraph now name
  `automation`, and the prefix waivers fall to the measurement
- automation runs borrow the brain read-only, as standing firings did
- the memory tidy rides the clock (automation.Tidy), gated on MachineIdle
- the sweep's fourth rule reaps stale errands and keeps any an automation
  was saved from
- an automation card answered from another window takes every key its own
  card drew (`2` was refused at the doorstep)
- cmd/codeaf: the ticker, the background repair, the standing seam and the
  host's standing cache are gone; the clock carries the tidy
- remote: Standing.* methods, ResolveStanding and the marked submit leave the
  wire; the held kind goes; the surface-door ledger drops to 18
- config: the background-checks row is retired with its key
- run: worker briefs close on the person's rules alone

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: watch names the idea, and the standing purpose goes

- `watch`'s description said lasting checks were `stand`'s, a tool that is
  gone; it now names an automation without naming a verb some belts lack
- the unused standing-check call purpose leaves; the replay tool still
  reads old logs that carry it
- the fixed prefix falls another 8 bytes and its waiver with it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the docs say what was built

- the design doc gains the typed grammar, the → keys, the quit warning as
  shipped, the store's notification claim, the kept `ask here` errands, the
  read-only brain and the tidy on the clock; the watch cost estimate it
  promised was never built and goes
- the guide, the README, FEATURES, LIMITS and the memory docs name
  automations and `/always` where they named standing orders; the README's
  standing screenshot goes with the page it showed
- AMBIENT and STANDING-ORDERS are marked superseded

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the kind's answer row is said to be the superset it is

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the reading says why it is handed its palette

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* e2e: automations replace standing orders in the end-to-end suite

Nothing in internal/e2e imports internal/standing or leans on a standing
door any more, so the package builds once those are deleted.

- The host guard proves the old-timer removal touches only the throwaway
  login: testdata/oldtimers runs RemoveOldTimers as a real program behind
  the guard, and the developer's tick and wake files, both names, are
  hashed around it. The guard also stands in for osascript and
  notify-send, and sets CODEAF_NO_AUTOMATIONS=1 on every launch whose
  scenario does not name it.
- The shared world keeps no ambient store and no standing answers; say
  and drain take none, and decline an automation card if one ever comes.
- The three standing lanes are deleted. TestAutomationsE2E replaces the
  three TestTUIE2E subtests that were about standing orders, with no key:
  ask here ending on an automation card (wide and narrow), and a typed
  reminder said by the clock into its conversation, as a notification and
  on the automations place, then the clock leaving on its own.
- The words table drops the standing rows, respells the ones automations
  renamed, and catches up with home's activity heading, the seven-place
  bar and the Spending tab's per-chat label; testHomeShape,
  testAnswerFromHome and testOneSpendFigure read what is drawn now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the tui3 and session test builds compile again

Three test files still named what the standing removal took away, so
neither package's tests built at this commit and no manual gate in them
could run: notice_test.go proved a retirement event that no longer
exists, and the usage tests asked for a spend subject that is now
SubjectAutomation.

- notice_test.go: the gesture is /automations, which fires
  eventAutomationsOpened.
- usage_ledger_test.go: an automation's run writes its line under the
  automation's id, and the rollup names the automation.
- usage_spend_test.go: the automation row and its subject word.

These are byte for byte the versions 61022e9 carries, so the two
branches agree on them when they meet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the e2e timing notes stop promising a standing pass

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the chat manual says what replaced standing orders

The chat corpus still taught standing orders — /standing, the stand card,
keeping an eye, the OS timer and `codeaf tick` — after automations had
replaced them. The chat answers from these pages alone, so it would have
offered a page, a key and a timer that no longer exist.

- automations.md is new: reminders, scheduled work and watches; the card
  and its answers; schedules and cron; /automations and its → verbs;
  history and what a run came to; where the news arrives; the clock that
  runs only while a window is open, missed runs marked late; cost limits;
  worktree or checkout; the typed /automations forms; ask here; rules as
  memories marked always; the automation and automation_report tools;
  where standing orders went; and what automations cannot do.
- keeping-an-eye.md and standing-orders.md are deleted. Every other page
  that described standing — home, keys, commands, places, screen,
  asking-from-home, the remote pages, models-and-cost, questions, tasks,
  what-i-can-do, what-i-remember, hints-and-tips and the rest — now says
  what the automations code does, quoting its strings.
- chat_test.go: the forty-nine probes that reached a deleted page are
  pointed at the page that answers them now, and fifty-six probes are
  added in the asker's words. The rerun and due-time tests follow.
- truth_test.go no longer imports internal/standing: the standing facts
  leave, and automation.DefaultTime and automation.DefaultUSD are pinned
  where the pages quote them.
- asked.go's wants follow the pages; lawregistry_test.go drops the two
  laws filed against keeping-an-eye; session's manual gate opens an
  automations store so `automation` is checked, and a second gate builds
  a run's belt so `automation_report` is too.
- The e2e due-time subtest still reaches home, and waits for the
  sentence that says where an automation's next time is shown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: internal/standing is deleted

Nothing imports it any more: the session, the doors, the wire, the
config, the manual's truth table and the end-to-end suite have all
moved to internal/automation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: home's tip leads with the command

A home tip says a key or a command first, and the one that taught saying
an automation did not, so home's row broke its own law.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a collection cannot gain a standing item

The kind names nothing codeaf runs any more. A row an older build wrote
can still be found and taken out; the schema keeps the kind so an older
build on the same machine still opens the database.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a conversation switched to is told what it missed

The missed runs were gathered only on a window's first reading, so a
conversation switched to in a window already open never heard them. Now
any conversation that comes to the front is asked about once, and a run
a window has drawn is not drawn twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the manual says when an errand that went nowhere is cleared

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: gofmt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the complexity ratchet holds the automations engine

The ratchet walked the standing ticker and inbox, which are gone; it now
walks the automations clock, store and runner. The run's Work held 25
decisions against a ceiling of 15, so it is split along its own phases:
the run's configuration, the turn watched for the two reasons to stop,
and what it came to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: comments stop describing standing orders as live

Comments in cmd/ and internal/ (internal/standing and internal/e2e left
alone) that still described the standing feature as current now say
what the code does: the automation tool, /automations, `codeaf clock`
and the rules marked always. Historical records are kept, with doc
links to deleted symbols turned into plain text or pointed at the
replacement, and every bracketed link a rewritten comment names
resolves.

Comments only: the token stream of every changed file is identical
outside comments, apart from one stray blank line in effortscope.go's
import block that gofmt removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a run of work stops at the daily spending limit

Standing firings were held to the person's daily limit; an automation's
work run is shaped like a task, which the turn's check passes over, so
it spent past the limit. It now asks before anything is made for it and
reads `your call` when the limit is reached. A watch's looks are not held
to it: each costs a fraction of a cent, and a refused look is news.

The design doc gets back the watch cost estimate, which is built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the suites pass without standing orders

- home settles its phone shape before it builds again; the band read
  that used to do it went with standing orders
- `/automations` has its fates on home: the place bare, a conversation
  for `add` and `edit`, home's own line for the id verbs
- `automation_report` is communication, and both automation tools have a
  folder-hold disposition; `usd` is a fractional argument
- the dead standing fields, the backlog fold, the held kind, a separator
  and three band orders are removed
- tests that still named standing words, `/standing` as a door or the
  standing ladder stamper now read the automations surface

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: ask an ask-here errand's approvals in its own pane

A call inside home's `ask here` errand that the approval policy grades
"ask" blocks inside the errand's session until that agent is answered.
errandEvent had no case for EventConsentRequest, and nothing else holds
the errand's agent, so the errand sat `working` on a question no screen
drew, and a `1` pressed at it went into the follow-up box.

- The pane now draws the approval under the call it is about, with the
  conversation's own question builder and renderer: `1 allow once` and
  `3 deny`. There is no `always` from the pane.
- The answer goes straight to the errand's agent (ResolveConsent), not
  through the block's door, whose receipt lands above the window's own
  box and whose `c change` would be answered by the window's engine.
- The row says `waiting on you` and sorts first; the live block gives
  way while the turn waits; the call's row keeps `allowed`/`denied`.
- The block's settle guard applies to the approval's digits and clicks,
  so a digit typed into a follow-up cannot allow an unread command.
- Approvals are dropped when the turn ends; several in one step are
  asked oldest first. Results pair to rows by call id.
- errandWait is renamed waitErrand so the harness's waiter law sees it
  and a test can hold a gated stream open.
- asking-from-home.md says all of this, and no longer sends approvals
  to `continue as a conversation`, which ends the waiting call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the word stands on the tab bar, between memory and spend

A place that appeared only while somebody stood in it was a room nobody knew
was there. Eight words need 84 columns, so a narrower frame folds spend and
settings behind more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: one strength, one write door, every line in front of every turn (WIP)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: banners through the terminal, closing pauses, and watches find the key

What the owner's walkthrough of the first build found, fixed:

- A banner is raised whether or not codeaf has the keyboard, so `r` on a
  reminder raises one too. In iTerm2 it is iTerm2's own (OSC 9), in Ghostty,
  kitty, WezTerm and foot the terminal's OSC 777, and clicking it brings the
  tab back. Elsewhere it is osascript with a sound, or notify-send with the
  logo. The first banner on a machine names the sending app once, linked to
  Notification settings. A codeaf-branded macOS banner needs a Developer ID:
  macOS 26 refuses an ad-hoc-signed applet silently.
- A run's line is also said on the message line of home or the place in
  front.
- Quitting never asks. A run closing codeaf cut off is told to nobody and runs
  again, once, when a window next opens.
- A watch's check passes over a model whose service has no key, down to the
  conversation's own model, and names the model and service when none is
  reachable. The clock re-reads the saved key before every run, and follows
  the newest window's environment (a salted fingerprint, never a value), so
  a key exported in one shell and not another no longer decides it.
- The typed form reads `at 6pm`, `at tomorrow 9am` and `at monday 9am`
  without quotes.
- The clock no longer runs the memory tidy, which the memory rework rules out.
- Home's since-you-left whisper no longer says watches run while codeaf is
  shut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the demo's cut-off run is one the person stopped, and the row-zero law starts at 84 columns

A run codeaf closing cut off now picks up again, which the demo's replay of
the rhythm cannot express. Eight words on the bar need 84 columns, so that
is where the bar is promised never to move. The since-you-left whisper says
what happened rather than what landed, which a first look must not claim.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: store, reflex and session tests for one strength (WIP)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: surface tests for one strength (WIP)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: wire, door and seeder tests for one strength (WIP)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the tidy, its clock types and the rule-consent floor are gone

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the manual, the settings row and the last stale seams match one strength

- what-i-remember is rewritten for one strength, the Memory tab, noticing and
  undo; the other chat pages stop describing the router, the always flag, the
  tidy, the shelf key and "memory is off"
- the settings row is "notice things to remember" and applies from the next turn
- the model's forget is seeded allow beside remember: both say what they did and
  /forget takes it back
- a far engine with no store says "memory is unavailable on this machine"
- a live switch to the lean profile keeps the memory block
- the speed and no-change tests read the noticing pass instead of the removed
  pre-turn recall and extractor

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the laws, the waivers and the docs follow one strength

- lane.RoleRecall goes with the pre-turn recall: a role nobody calls is owed a
  deletion, and the provider tests that borrowed it use the tool role
- the complexity ratchet watches the memory engine instead of the deleted
  contextual files; learnFromTurn, importMemoryFile and MemorySnapshot split
  under its ceiling
- both prefix waivers fall to the measurement (52,519 and 44,915), in PERF.md too,
  and PERF.md's memory sections describe the one bounded block
- tests that pinned the old shape (lean and tool-less pages dropped memory, an
  explained override became a memory, the settings row needed a restart) now
  pin the new one
- the settings detail leads with what off does, and "remember across chats"
  still finds the row
- docs/memory-architecture.md describes what memory is now; the contextual
  page is a pointer into history; the audit that started this is kept

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: a test name stops spelling the old product name

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the change entry for Agent-Field#1830

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the change entry for Agent-Field#1831

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: a run's whole result is read in its history, and its banner carries it

The run under the cursor in an automation's history shows its full report in
ordinary text, and the history opens on the newest run. A banner says what the
run came to and up to 180 characters of its report, without repeating the title.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the Memories tab reads like Activity, and /forget is gone

- the tab is "Memories"; typing "memory" still finds it, and eight tab words
  now need 86 columns
- groups are rows of their own that open on → and fold on ←, never enter; lines
  hang on tree connectors with kept-by and age columns, and a pane reads the
  cursor row out on frames of 110 columns or more
- the words being written on the add row or in a line's editor are drawn in
  that row, with the caret; before, they were typed into nothing visible
- /forget and the undo stack behind it are removed: a person forgets and puts
  back on the tab, the model's forget stays, and every receipt made on the
  person's behalf says "see or forget it on the Memories tab"
- wire Memory.ForgetQuery goes with the command, folded into Version 22

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: the review's fixes

- Deleting an automation stops its run in hand: the clock asks whether each
  run's automation still exists, since the delete takes the run rows (and any
  stop request) with it.
- A rhythm of days that would overflow a duration is refused, not wrapped.
- A files watch's walk checks its budget and its run's context on every
  entry, so a rarely matching glob over a whole home no longer walks it all.
- The judge's client is kept per model and account, so a replaced key is used.
- A window's presence file is locked and written before it is renamed into
  place, so a counter can no longer remove a window being opened.
- `codeaf do` reads the rules before its deadline starts.
- A typed id needs four characters, and the refusal says where the id comes
  from. A ~ folder crosses unexpanded and the store reads it as its own
  machine's home, so a line typed over --host names the far machine's folder.
- Each automation keeps its last hundred runs; forgotten and deleted runs'
  folders go, except a folder holding a worktree, whose changes are the
  person's to review.
- A watch's banner says its own line, not what its look saw.
- The old timers' files are removed before their jobs are unloaded, by label.
- Stale docs and comments; the audit note is dropped from the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the catalogue test reads the Memories tab row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the bound is the store's, held inside every write

Review fixes for Agent-Field#1830.

- the 4,800-rune bound, the line cost and the quoting move to the store
  (memory_room.go); every door that makes a line active — write, replace,
  reword, move, put back — is measured inside its write transaction against
  every block the owner reaches, so a line kept everywhere cannot overflow
  another project, and two writers with room for one admit one
- duplicates are the target owner's only; a move or a replacement onto words
  already kept lets the copy go instead of keeping two, and a forgotten line
  cannot be moved
- a store an earlier build filled past the bound lets its always rules, then
  project, machine and person lines ride (FitMemories), and the conversation
  says once how many don't fit
- the model's remember and forget act only on a turn the person typed
- a noticed line is said on the standing lane when the turn's stream has
  closed; an ask-here errand is not noticed
- memories_fts stays this release for older engines still running
- the settings row reads one spelling; the tab's foot over an empty filter
  says esc; the project lookup's wire error is no longer "no project"
- stale comments, names and docs; the audit notes and the contextual doc go

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: the guide's tool table names automation, not the removed stand

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: tell a person who had memory off, once per machine, that their lines ride

The owner's ruling on R8: on the first start after the upgrade, a person whose
memory row was off is told once that their N kept lines now ride every
conversation they hold in, with the Memories tab to forget them. The marker is
created exclusively beside the store on that first start whatever the setting
says, so it is said once per machine and never to someone who turns noticing
off later. No line changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: a woken turn does not arm the model's verbs; the person's line does

A turn a task's landing or a job's ending opens is empty and marked a wake, and
it armed remember/forget because it carried no authored mark. The verbs now arm
only on a non-empty line the person typed, on their line drained into a turn
mid-way, and on the follow-up turn started to answer a line they typed in the
last seconds of the turn before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: a line noticed while its conversation is out of sight waits for the person

The keeper holds a conversation's standing lane while another is on screen,
and it drained memory's notices to nowhere. Memory's notices now say they are
in no record (Event.Unrecorded); the keeper keeps them, files them with the
conversation's parked receipts, and coming back draws them there. A turn's own
lines wait for the turn to end, since coming back mid-turn replays them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: a full refusal says whose block it would overflow; an already-kept correction is said

The store's refusal now carries the owner it would overflow, and every door
says it from the conversation's own view: here, for <project>, or in another
project. Over --host the name in the text is compared instead. Noticing a
correction that was already kept lets the old line go and now says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: test the bound on replacement, the unbounded import and a held second writer

A seam inside the room check holds the first writer in its transaction; the
second must not read the room until the first commits, and then finds none.
The test fails with deferred transactions. Replacement is measured, and the
legacy import is kept whole past the bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: words already kept are not put back twice; an unknown project counts nothing

Putting back a line, or rewording one, onto words its owner already keeps
active is refused with store.ErrMemoryKept, and the tab says "already kept".
When the engine cannot say which project this is, the tab takes nothing from
the failed answer and its head row draws no don't-fit count. Tests cover the
tab's refusal words, the no-match hint and the no-project note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: a stub keeps the changelog's contextual-memory link; its terminal recipe goes

CHANGELOG.md links docs/contextual-memory.md, so a one-line page says it is
retired and where its contents are. The terminal acceptance recipe and its
recorder tested the removed evidence layer, and are deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the manual, the change entry and the design say what round two changed

Full receipts say whose block; words already kept are refused on put-back
and rewording; an already-kept correction is said; a line noticed out of sight
waits for the person; a woken turn arms the verbs only once the person types;
an unknown project counts nothing that doesn't fit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* memory: the turn that answers the person carries it on its own message

A stale flag could outlive a failed, declined, vision or abandoned turn and
arm the next task's landing. The drain now reports whether it heard the
person: mid-turn that arms the rest of the turn, and at the turn's end the
follow-up wake's opening carries answersPerson. No agent state is left. A
real-loop test fails a turn after a steer and checks the next wake is not
armed; the keeper's turn notices, the hand-off on the way forward and the
unrecorded mark are each pinned by a test that fails without them. The manual
says an answer to a question on an idle conversation does not arm the verbs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: the change entry records the re-measured prefix waivers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… is refused (Agent-Field#1837)

* automations: a finished reminder moved later wakes again; a late save is refused

Moving a FINISHED one-time reminder later with `e` on /automations could leave
the row finished. Two things combined:

- CommandLine wrote a one-time `at` to the minute, so an `in 2m` reminder
  (seconds precision) came back earlier in the box, and "the next minute"
  could be seconds away.
- Store.Update saved a new one-time moment that had already passed while the
  card was up as the next run; the clock took it at once and the reminder was
  finished again a beat after the save.

Fixes:
- The edit line keeps a moment's seconds (and fraction); parseMoment reads them.
- Store.Update refuses a changed one-time moment that is not after now.
- An edit is refused for a past moment only when it moves the moment, so a
  finished reminder can be renamed.
- automation.NextAfterChange is the one rule both doors' cards use for the
  next run, so the typed edit no longer promises a run to a paused automation
  or a fresh slot to an unchanged rhythm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* changelog: a finished reminder moved later wakes again (Agent-Field#1837)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* automations: review fixes — paused receipt, DST round trip, manual

- A typed edit of a paused automation says "still paused — resume starts it
  again" instead of a next slot it does not run at.
- The edit line writes a moment in a fall-back's repeated hour with its
  offset, so it reads back as the same instant.
- A moment that passed in the current minute is refused to the second.
- The Store.Update comment names errPassed, and that a zone-only change to a
  one-time schedule is refused too.
- DESIGN.md narrowed: only a change is refused at save time; an add answered
  late still runs once.
- Manual: a section on a change refused at save time and renaming a finished
  reminder, the refusal list, and three retrieval probes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gent-Field#1836)

* tui3: make the switch and plan test fakes safe for the off-loop readers

The -race failures in the held-send tests and the run-stop card test were in
the test seams, not the surface. The kept conversation's watcher calls
Attach from its own goroutine, and the door line asks PlanTasks,
PlanTaskPage and the plan verbs off the loop; the real agents take their
locks for all of these. The fakes did not:

- switchAgent: Attach and its stop guard running/backlog/stops with a
  mutex; tests that flip running while a watcher is live use setRunning.
- planFake: PlanTasks answers a copy as the store does; setStatus writes a
  new slice instead of over the one planAppWith handed the surface; pages
  are guarded, and the program-room test writes them through setPage.

Fixes the four held-send races, TestStopOnTheRunsOwnPageRaisesTheCardAndTheCardStopsTheRun,
and three more of the same class found on dev: TestAProgramRoomReadsTheLandingTheStoreEndedAhead,
TestTheCancelKeyOnAPlanRowEndsItThroughTheStore, TestPOnAPlanRowPausesThenResumes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: change entry for the held-send race fakes (Agent-Field#1836)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: keep the Agent-Field#1836 change entry title under 100 characters

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* tui3: route the plan fakes' test writes through their lock; atomic rail counters

Review follow-ups on Agent-Field#1836:

- railPlanCounter's rows/pages counts are atomic; they are bumped by the
  surface's off-loop reads.
- planFake gains editRows (in place, keeping planAppWith's aliasing) and
  setPlan; every direct test write to fake.plan and fake.pages goes through
  them or setPage.
- switchAgent.mu's comment says exactly what it covers.
- The change entry's invalidates line is cut to the rules' length and drops
  surface for this test-only change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s what it says again (Agent-Field#969) (Agent-Field#1796)

* census: the call row carries the demanded set, so served != lane means what it says again (Agent-Field#969)

Since the chooser demands the whole admitted set (provider.only with
fallbacks off), the router may serve any member of it, so Record.Lane
(the ranked head) stopped being the only machine the request would
accept. The census read served != lane as the router going somewhere we
did not choose, which after the set-demand is often the router choosing
a different member of the set we did choose.

Add Record.Lanes []string, filled from laneChoice.Only when the demand
is still being sent, carrying the whole set when it has two or more
members (a one-machine demand is left to Lane alone). The census counts
asked != served only when served fell OUTSIDE the admitted set.

callrows.Row embeds calllog.Record, so the census reads the new field
the day it lands.

* docs: change entry for Agent-Field#1796 (demanded set on the call row)

* address review: record the demand that actually travelled, not the original choice

ZeroPoint95's review on Agent-Field#1796 caught that demandedLanes read the original
laneChoice.Only, so a rescue (sends only:[B]) and a narrowed retry (drops a
refused machine) recorded the whole original set and misattributed Lane.

Capture provider.only as wirePreferences composed it, at encode time, onto
the trace; carry it onto the openAttempt so a finish row written after a
later attempt re-encoded still describes its own. demandedLanes now reads
that composed set, and recordedLane names the single machine a narrowed
attempt really demanded rather than the ranked head it recovered from.

Adds the two wire-versus-log regression tests the review asked for: a rescue
arm records only its one machine, and a narrowed retry does not keep the set
it no longer demands and attributes to the machine it does.

* address review 2: preserve the demanded set through the hopped close, fix docs

ZeroPoint95's second review caught that closeOpenAttempt clears trace.open
before recording, so a finish row built on the fallback close read the latest
encode's demand rather than the closed attempt's. Carry the attempt's snapshot
through recordFacts.demandedOnly and read it off the ended row in
bodyDemandedOnly, keyed on ended (set only on that row) so an attempt closed
carrying no demand is not handed a later one.

Also remove the stale duplicated demandedLanes doc that still described reading
laneChoice.Only, and correct the Record.Lanes doc: Lane is a member of the set
but not necessarily its first element, since a three-to-two retry can keep the
original ranked head as Lane while Lanes names the surviving pair.

Adds TestAHoppedAttemptKeepsItsOwnDemandedSetThroughTheClose, which fails
without the carry and passes with it.

* docs: clarify call demand snapshot comments

---------

Co-authored-by: ZeroPoint95 <329227198+ZeroPoint95@users.noreply.github.com>
* docs: describe the built-in coding, security and review specialists

* docs: record the specialist README corrections

* docs: refine specialist caveat and unwrap touched prose
…nt-Field#1546) (Agent-Field#1842)

* session: the daily spend ceiling binds task and errand turns too (Agent-Field#1546)

railBlockLocked skipped the daily budget check for InTask runners and the
home Errand, and the crew guard that also enforces it is absent under
--one-model and for an InTask agent with no crew. So a chat /task past the
day's limit, and a task under --one-model, kept spending with no refusal
while headless codeaf do and standing firings honoured the limit.

Remove the InTask/Errand carve-out so the daily ceiling is checked on every
turn-starting path. It is a ceiling read of the shared ledger, never a
tally, so a path already held to the crew's own day cap is refused in two
places, never charged twice.

* docs: change entry for Agent-Field#1842 (daily ceiling on every path)

* address review: carry the selected daily budget and spend preauthorization into workers

ZeroPoint95's review on Agent-Field#1842 caught that the daily check read the default
profile for workers (which carry no ProfileDir), so a worker refused under a
higher selected limit and spent past a lower one, and that it re-applied the
limit --yes-spend deliberately lifts.

- Resolve the daily ceiling once at the root (where ProfileDir is set) and
  carry it as Config.DailyBudgetUSD; dailyCeilingUSD reads live from the
  profile for a root and the carried figure for a worker, never a profile at
  an empty path.
- Carry Config.SpendPreauthorized (--yes-spend / CODEAF_PREAUTHORIZE_SPEND=1)
  into workers; it lifts the daily check and nothing else, matching the crew
  guard.
- Thread both through all three worker constructors: the task-child
  (task_run.go), the adaptive-run worker (orchestrate.go) and the plan-run
  bash worker (run.CrewFactory, which gains a preauthorized parameter).

Adds regressions: a worker held to its carried selected budget (higher allows,
lower refuses) not the default, and preauthorization lifting the daily ceiling
while a conversation limit stays in force.

* fix: preserve daily budget authority in roots and task checks

---------

Co-authored-by: ZeroPoint95 <329227198+ZeroPoint95@users.noreply.github.com>
…ld#1877)

* docs: record DeepSWE harness versions and release context

* docs: add DeepSWE version evidence change entry (Agent-Field#1877)

* docs: use public senior-dev lineage and simplify version records
…#1870)

* fix: refresh Codex catalog client version

* docs: record Codex catalog version fix for Agent-Field#1870

* test: cover version-gated Codex discovery through both catalog doors

Pin the backend fixture independently of the shared client version so reverting the advertised version hides newer models in both direct and translated listings. Preserve visibility filtering and cached reasoning metadata.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Abir Abbas <abirabbas1998@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix: build valid SQLite file URIs on Windows

* docs: record Windows SQLite URI fix for Agent-Field#1868

* test: preserve POSIX SQLite URIs and cover Windows path forms

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Abir Abbas <abirabbas1998@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…1845)

* fix(session): require explicit work orders for auto tasks

* docs(changelog): add entry for PR 1845

* test(session): tolerate prompt line wrapping

* fix(session): distinguish polite work requests from questions

* test(session): cover routing authorization and stopped-result scope

Separate feasibility questions from explanation requests in the shared route
contract and the searchable chat manual. Pin examples with their complete
classification clauses, and prove stopped-result suppression does not block
fresh requests or normal remediation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(manual): make stopped-result routing reachable through search

Give the stopped-result rule its own section so the manual context includes
both the restart guard and the fresh-human-request exception. Pin the actual
retrieved answer, since merely finding the long tasks page hid the rule beyond
the section limit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(session): judge human steering during stopped-result wakes

Read current-turn person provenance and judge the newly consumed instruction, including a verbatim repeat of the stopped request.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(session): scope stopped-result routing to each delivered task

Keep attempt snapshots and effective obligations distinct even when sibling tasks inherit the same request. Skip result-only cancelled work before classification, and show both readers only the independent eligible work with explicit cancellation boundaries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(session): restore task cancellation from its saved ending

Derive the stopped runtime flag from the persisted stopped ending. Keep restored cancelled results out of routing while ordinary failed results retain repair eligibility.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(session): limit stopped-result guard to unambiguous result-only wakes

Keep dev's routing inputs, floors and rulings whenever a human speaks, results
are mixed, or provenance is incomplete. Skip both classifiers only when every
delivered result is stopped for the current request in a result-only wake.

Remove scoped eligible-work questions, attempt tags and snapshot deduplication.
Retain frozen stop provenance and restored cancellation for the stop-only case.
Preserve untagged news through batching without changing existing owed asks.
Compare production wake, Submit, retry, cancel and recovery probes against dev,
and narrow the manual and change entry to the conservative guarantee.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(session): drain steering before reading routes in stopped-wake tests

Both fresh-human stopped-wake tests submitted a steer from the answer hook but let the turn race the boundary drain, so CI could count one route reading instead of two. Drain inside the hook, as the mixed-result steering test already does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Abir Abbas <abirabbas1998@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…gent-Field#1884)

* docs(agents): say CI is real, Spark is private and no key is normal

Agents in cloud sessions kept reporting that the repository has no CI and
no Spark. CI is GitHub Actions and runs on every pull request; gh fails
there only because its token does not authenticate, so the guide now
points at the GitHub MCP tools. Spark is the owner's private machine and
was never a step anyone else owed. Add a when-to-run table so cloud
sessions lean on touched packages instead of repeating it locally, and
drop the PR template's line about the deleted known-red ledger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtiPtzDsHa753NHJBpKYpn

* docs(changelog): add entry for PR 1884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtiPtzDsHa753NHJBpKYpn

---------

Co-authored-by: Claude <noreply@anthropic.com>
…gent-Field#1454)

The tasks page located task.parallel in category spending, but /settings
shows it under Tasks as 'tasks at once' (settings.go's CategoryTasks), so
someone following the page searched the wrong section. Name the section
and the row exactly as drawn, and add manual probes that reach the tasks
page for the setting.
The generic probes only asserted that some section on the tasks page was
returned, so restoring the former Spending wording left them green. Put the
issue's exact query vocabulary in the section heading and add a focused test
that finds that section, requires 'under Tasks as tasks at once', and rejects
the former category.

The test fails when the old wording is restored and passes with the correction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The tasks manual sends people to Spending for the tasks-at-once setting